blob: a74a2a7ace429e28aad5624bd4bd2987649b257b [file] [log] [blame]
/*
* Shell Folder stuff (...and all the OLE-Objects of SHELL32.DLL)
*
* Copyright 1997 Marcus Meissner
* Copyright 1998 Juergen Schmied
*
* !!! currently work in progress on all classes !!!
* <contact juergen.schmied@metronet.de, 980624>
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "ole.h"
#include "ole2.h"
#include "debug.h"
#include "compobj.h"
#include "interfaces.h"
#include "shlobj.h"
#include "winerror.h"
#include "winnls.h"
/* FIXME should be moved to a header file. IsEqualGUID
is declared but not exported in compobj.c !!!*/
#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
/***************************************************************************
* GetNextElement (internal function)
*
* RETURNS
* LPSTR pointer to first, not yet parsed char
*/
LPSTR GetNextElement(
LPSTR pszNext, /*[IN] string to get the element from*/
LPSTR pszOut, /*[IN] pointer to buffer whitch receives string*/
DWORD dwOut) /*[IN] length of pszOut*/
{ LPSTR pszTail = pszNext;
DWORD dwCopy;
TRACE(shell,"(%s %p %lx)\n",pszNext, pszOut, dwOut);
if(!pszNext || !*pszNext)
return NULL;
while(*pszTail && (*pszTail != '\\'))
{ pszTail++;
}
dwCopy=((LPBYTE)pszTail-(LPBYTE)pszNext)/sizeof(CHAR)+1;
lstrcpyn32A(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
if(*pszTail)
{ pszTail++;
}
TRACE(shell,"--(%s %s %lx)\n",pszNext, pszOut, dwOut);
return pszTail;
}
/**************************************************************************
* IClassFactory Implementation
*/
static HRESULT WINAPI IClassFactory_QueryInterface(LPCLASSFACTORY,REFIID,LPVOID*);
static ULONG WINAPI IClassFactory_AddRef(LPCLASSFACTORY);
static ULONG WINAPI IClassFactory_Release(LPCLASSFACTORY);
static HRESULT WINAPI IClassFactory_CreateInstance();
/*static HRESULT WINAPI IClassFactory_LockServer();*/
/**************************************************************************
* IClassFactory_VTable
*/
static IClassFactory_VTable clfvt = {
IClassFactory_QueryInterface,
IClassFactory_AddRef,
IClassFactory_Release,
IClassFactory_CreateInstance,
/* IClassFactory_LockServer*/
};
/**************************************************************************
* IClassFactory_Constructor
*/
LPCLASSFACTORY IClassFactory_Constructor()
{ LPCLASSFACTORY lpclf;
lpclf= (LPCLASSFACTORY)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactory));
lpclf->ref = 1;
lpclf->lpvtbl = &clfvt;
TRACE(shell,"(%p)->()\n",lpclf);
return lpclf;
}
/**************************************************************************
* IClassFactory::QueryInterface
*/
static HRESULT WINAPI IClassFactory_QueryInterface(
LPCLASSFACTORY this, REFIID riid, LPVOID *ppvObj)
{ char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",this,xriid);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
{ *ppvObj = this;
}
else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
{ *ppvObj = (IClassFactory*)this;
}
if(*ppvObj)
{ (*(LPCLASSFACTORY*)ppvObj)->lpvtbl->fnAddRef(this);
TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE(shell,"-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/******************************************************************************
* IClassFactory_AddRef
*/
static ULONG WINAPI IClassFactory_AddRef(LPCLASSFACTORY this)
{ TRACE(shell,"(%p)->(count=%lu)\n",this,this->ref);
return ++(this->ref);
}
/******************************************************************************
* IClassFactory_Release
*/
static ULONG WINAPI IClassFactory_Release(LPCLASSFACTORY this)
{ TRACE(shell,"(%p)->(count=%lu)\n",this,this->ref);
if (!--(this->ref))
{ TRACE(shell,"-- destroying IClassFactory(%p)\n",this);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
/******************************************************************************
* IClassFactory_CreateInstance
*/
static HRESULT WINAPI IClassFactory_CreateInstance(
LPCLASSFACTORY this, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
{ LPSHELLFOLDER pSHFolder;
HRESULT hResult=E_OUTOFMEMORY;
char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE(shell,"%p->(%p,\n\tIID:\t%s)\n",this,pUnknown,xriid);
*ppObject = NULL;
if(pUnknown)
{ return CLASS_E_NOAGGREGATION;
}
if (IsEqualIID(riid, &IID_IShellFolder))
{ pSHFolder = IShellFolder_Constructor(NULL,NULL);
if(pSHFolder)
{ hResult = pSHFolder->lpvtbl->fnQueryInterface(pSHFolder,riid, ppObject);
pSHFolder->lpvtbl->fnRelease(pSHFolder);
TRACE(shell,"-- ShellFolder created: (%p)->%p\n",this,*ppObject);
}
}
else
{ FIXME(shell,"unknown IID requested\n\tIID:\t%s\n",xriid);
hResult=E_NOINTERFACE;
}
return hResult;
}
/******************************************************************************
* IClassFactory_LockServer
*/
/*static HRESULT WINAPI IClassFactory_LockServer(LPCLASSFACTORY this, BOOL)
{ TRACE(shell,"%p->(), not implemented\n",this)
return E_NOTIMPL;
}
*/
/**************************************************************************
* IEnumIDList Implementation
*/
static HRESULT WINAPI IEnumIDList_QueryInterface(LPENUMIDLIST,REFIID,LPVOID*);
static ULONG WINAPI IEnumIDList_AddRef(LPENUMIDLIST);
static ULONG WINAPI IEnumIDList_Release(LPENUMIDLIST);
static HRESULT WINAPI IEnumIDList_Next(LPENUMIDLIST,ULONG,LPITEMIDLIST*,ULONG*);
static HRESULT WINAPI IEnumIDList_Skip(LPENUMIDLIST,ULONG);
static HRESULT WINAPI IEnumIDList_Reset(LPENUMIDLIST);
static HRESULT WINAPI IEnumIDList_Clone(LPENUMIDLIST,LPENUMIDLIST*);
static BOOL32 WINAPI IEnumIDList_CreateEnumList(LPENUMIDLIST,LPCSTR, DWORD);
static BOOL32 WINAPI IEnumIDList_AddToEnumList(LPENUMIDLIST,LPITEMIDLIST);
static BOOL32 WINAPI IEnumIDList_DeleteList(LPENUMIDLIST);
/**************************************************************************
* IEnumIDList_VTable
*/
static IEnumIDList_VTable eidlvt = {
IEnumIDList_QueryInterface,
IEnumIDList_AddRef,
IEnumIDList_Release,
IEnumIDList_Next,
IEnumIDList_Skip,
IEnumIDList_Reset,
IEnumIDList_Clone,
IEnumIDList_CreateEnumList,
IEnumIDList_AddToEnumList,
IEnumIDList_DeleteList
};
/**************************************************************************
* IEnumIDList_Constructor
*/
LPENUMIDLIST IEnumIDList_Constructor( LPCSTR lpszPath, DWORD dwFlags, HRESULT* pResult)
{ LPENUMIDLIST lpeidl;
lpeidl = (LPENUMIDLIST)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumIDList));
lpeidl->ref = 1;
lpeidl->lpvtbl = &eidlvt;
lpeidl->mpFirst=NULL;
lpeidl->mpLast=NULL;
lpeidl->mpCurrent=NULL;
TRACE(shell,"(%p)->(%s %lx %p)\n",lpeidl,lpszPath,dwFlags,pResult);
lpeidl->mpPidlMgr=PidlMgr_Constructor();
if (!lpeidl->mpPidlMgr)
{ if (pResult)
{ *pResult=E_OUTOFMEMORY;
HeapFree(GetProcessHeap(),0,lpeidl);
return NULL;
}
}
if(!IEnumIDList_CreateEnumList(lpeidl, lpszPath, dwFlags))
{ if(pResult)
{ *pResult = E_OUTOFMEMORY;
HeapFree(GetProcessHeap(),0,lpeidl->mpPidlMgr);
HeapFree(GetProcessHeap(),0,lpeidl);
return NULL;
}
}
TRACE(shell,"-- (%p)->()\n",lpeidl);
return lpeidl;
}
/**************************************************************************
* EnumIDList::QueryInterface
*/
static HRESULT WINAPI IEnumIDList_QueryInterface(
LPENUMIDLIST this, REFIID riid, LPVOID *ppvObj)
{ char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
{ *ppvObj = this;
}
else if(IsEqualIID(riid, &IID_IEnumIDList)) /*IEnumIDList*/
{ *ppvObj = (IEnumIDList*)this;
}
if(*ppvObj)
{ (*(LPENUMIDLIST*)ppvObj)->lpvtbl->fnAddRef(this);
TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE(shell,"-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/******************************************************************************
* IEnumIDList_AddRef
*/
static ULONG WINAPI IEnumIDList_AddRef(LPENUMIDLIST this)
{ TRACE(shell,"(%p)->()\n",this);
return ++(this->ref);
}
/******************************************************************************
* IEnumIDList_Release
*/
static ULONG WINAPI IEnumIDList_Release(LPENUMIDLIST this)
{ TRACE(shell,"(%p)->()\n",this);
if (!--(this->ref))
{ TRACE(shell," destroying IEnumIDList(%p)\n",this);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
/**************************************************************************
* IEnumIDList_Next
*/
static HRESULT WINAPI IEnumIDList_Next(
LPENUMIDLIST this,ULONG celt,LPITEMIDLIST * rgelt,ULONG *pceltFetched)
{ ULONG i;
HRESULT hr = S_OK;
LPITEMIDLIST temp;
TRACE(shell,"(%p)->(%ld,%p, %p)\n",this,celt,rgelt,pceltFetched);
*rgelt=0;
if(celt > 1 && !pceltFetched)
{ return E_INVALIDARG;
}
for(i = 0; i < celt; i++)
{ if(!(this->mpCurrent))
{ hr = S_FALSE;
break;
}
temp = this->mpPidlMgr->lpvtbl->fnCopy(this->mpPidlMgr, this->mpCurrent->pidl);
rgelt[i] = temp;
this->mpCurrent = this->mpCurrent->pNext;
}
if(pceltFetched)
{ *pceltFetched = i;
}
return hr;
}
/**************************************************************************
* IEnumIDList_Skip
*/
static HRESULT WINAPI IEnumIDList_Skip(
LPENUMIDLIST this,ULONG celt)
{ DWORD dwIndex;
HRESULT hr = S_OK;
TRACE(shell,"(%p)->(%lu)\n",this,celt);
for(dwIndex = 0; dwIndex < celt; dwIndex++)
{ if(!this->mpCurrent)
{ hr = S_FALSE;
break;
}
this->mpCurrent = this->mpCurrent->pNext;
}
return hr;
}
/**************************************************************************
* IEnumIDList_Reset
*/
static HRESULT WINAPI IEnumIDList_Reset(LPENUMIDLIST this)
{ TRACE(shell,"(%p)\n",this);
this->mpCurrent = this->mpFirst;
return S_OK;
}
/**************************************************************************
* IEnumIDList_Clone
*/
static HRESULT WINAPI IEnumIDList_Clone(
LPENUMIDLIST this,LPENUMIDLIST * ppenum)
{ TRACE(shell,"(%p)->() to (%p)->() E_NOTIMPL\n",this,ppenum);
return E_NOTIMPL;
}
/**************************************************************************
* EnumIDList_CreateEnumList()
* fixme: devices not handled
* fixme: add wildcards to path
*/
static BOOL32 WINAPI IEnumIDList_CreateEnumList(LPENUMIDLIST this, LPCSTR lpszPath, DWORD dwFlags)
{ LPITEMIDLIST pidl=NULL;
WIN32_FIND_DATA32A stffile;
HANDLE32 hFile;
TRACE(shell,"(%p)->(%s %lx) \n",this,lpszPath,dwFlags);
/*enumerate the folders*/
if(dwFlags & SHCONTF_FOLDERS)
{ /* special case - we can't enumerate the Desktop level Objects (MyComputer,Nethood...
so we need to fake an enumeration of those.*/
if(!lpszPath)
{ //create the pidl for this item
pidl = this->mpPidlMgr->lpvtbl->fnCreateDesktop(this->mpPidlMgr);
if(pidl)
{ if(!IEnumIDList_AddToEnumList(this, pidl))
return FALSE;
}
else
{ return FALSE;
}
}
else
{ hFile = FindFirstFile32A(lpszPath,&stffile);
do
{ if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
//create the pidl for this item
/* fixme: the shortname should be given too*/
pidl = this->mpPidlMgr->lpvtbl->fnCreateFolder(this->mpPidlMgr, stffile.cFileName);
if(pidl)
{ if(!IEnumIDList_AddToEnumList(this, pidl))
return FALSE;
}
else
{ return FALSE;
}
} while( FindNextFile32A(hFile,&stffile));
FindClose32 (hFile);
}
}
//enumerate the non-folder items (values)
if(dwFlags & SHCONTF_NONFOLDERS)
{ hFile = FindFirstFile32A(lpszPath,&stffile);
do
{ if (! (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
//create the pidl for this item
/* fixme: the shortname should be given too*/
pidl = this->mpPidlMgr->lpvtbl->fnCreateFolder(this->mpPidlMgr, stffile.cFileName);
if(pidl)
{ if(!IEnumIDList_AddToEnumList(this, pidl))
{ return FALSE;
}
}
else
{ return FALSE;
}
} while( FindNextFile32A(hFile,&stffile));
FindClose32 (hFile);
}
return TRUE;
}
/**************************************************************************
* EnumIDList_AddToEnumList()
*/
static BOOL32 WINAPI IEnumIDList_AddToEnumList(LPENUMIDLIST this,LPITEMIDLIST pidl)
{ LPENUMLIST pNew;
TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
pNew = (LPENUMLIST)HeapAlloc(GetProcessHeap(),0,sizeof(ENUMLIST));
if(pNew)
{ //set the next pointer
pNew->pNext = NULL;
pNew->pidl = pidl;
//is this the first item in the list?
if(!this->mpFirst)
{ this->mpFirst = pNew;
this->mpCurrent = pNew;
}
if(this->mpLast)
{ //add the new item to the end of the list
this->mpLast->pNext = pNew;
}
//update the last item pointer
this->mpLast = pNew;
TRACE(shell,"(%p)->(first=%p, last=%p)\n",this,this->mpFirst,this->mpLast);
return TRUE;
}
return FALSE;
}
/**************************************************************************
* EnumIDList_DeleteList()
*/
static BOOL32 WINAPI IEnumIDList_DeleteList(LPENUMIDLIST this)
{ LPENUMLIST pDelete;
TRACE(shell,"(%p)->()\n",this);
while(this->mpFirst)
{ pDelete = this->mpFirst;
this->mpFirst = pDelete->pNext;
//free the pidl
this->mpPidlMgr->lpvtbl->fnDelete(this->mpPidlMgr,pDelete->pidl);
//free the list item
HeapFree(GetProcessHeap(),0,pDelete);
}
this->mpFirst = this->mpLast = this->mpCurrent = NULL;
return TRUE;
}
/***********************************************************************
* IShellFolder implementation
*/
/*LPSHELLFOLDER IShellFolder_Constructor();*/
static HRESULT WINAPI IShellFolder_QueryInterface(LPSHELLFOLDER,REFIID,LPVOID*);
static ULONG WINAPI IShellFolder_AddRef(LPSHELLFOLDER);
static ULONG WINAPI IShellFolder_Release(LPSHELLFOLDER);
static HRESULT WINAPI IShellFolder_Initialize(LPSHELLFOLDER,LPCITEMIDLIST);
static HRESULT WINAPI IShellFolder_ParseDisplayName(LPSHELLFOLDER,HWND32,LPBC,LPOLESTR32,DWORD*,LPITEMIDLIST*,DWORD*);
static HRESULT WINAPI IShellFolder_EnumObjects(LPSHELLFOLDER,HWND32,DWORD,LPENUMIDLIST*);
static HRESULT WINAPI IShellFolder_BindToObject(LPSHELLFOLDER,LPCITEMIDLIST,LPBC,REFIID,LPVOID*);
static HRESULT WINAPI IShellFolder_BindToStorage(LPSHELLFOLDER,LPCITEMIDLIST,LPBC,REFIID,LPVOID*);
static HRESULT WINAPI IShellFolder_CompareIDs(LPSHELLFOLDER,LPARAM,LPCITEMIDLIST,LPCITEMIDLIST);
static HRESULT WINAPI IShellFolder_CreateViewObject(LPSHELLFOLDER,HWND32,REFIID,LPVOID*);
static HRESULT WINAPI IShellFolder_GetAttributesOf(LPSHELLFOLDER,UINT32,LPCITEMIDLIST*,DWORD*);
static HRESULT WINAPI IShellFolder_GetUIObjectOf(LPSHELLFOLDER,HWND32,UINT32,LPCITEMIDLIST*,REFIID,UINT32*,LPVOID*);
static HRESULT WINAPI IShellFolder_GetDisplayNameOf(LPSHELLFOLDER,LPCITEMIDLIST,DWORD,LPSTRRET);
static HRESULT WINAPI IShellFolder_SetNameOf(LPSHELLFOLDER,HWND32,LPCITEMIDLIST,LPCOLESTR32,DWORD,LPITEMIDLIST*);
/***********************************************************************
*
* IShellFolder_VTable
*/
static struct IShellFolder_VTable sfvt = {
IShellFolder_QueryInterface,
IShellFolder_AddRef,
IShellFolder_Release,
IShellFolder_Initialize,
IShellFolder_ParseDisplayName,
IShellFolder_EnumObjects,
IShellFolder_BindToObject,
IShellFolder_BindToStorage,
IShellFolder_CompareIDs,
IShellFolder_CreateViewObject,
IShellFolder_GetAttributesOf,
IShellFolder_GetUIObjectOf,
IShellFolder_GetDisplayNameOf,
IShellFolder_SetNameOf
};
/**************************************************************************
* IShellFolder_Constructor
*/
LPSHELLFOLDER IShellFolder_Constructor(LPSHELLFOLDER pParent,LPITEMIDLIST pidl) {
LPSHELLFOLDER sf;
DWORD dwSize=0;
WORD wLen;
sf = (LPSHELLFOLDER)HeapAlloc(GetProcessHeap(),0,sizeof(IShellFolder));
sf->ref = 1;
sf->lpvtbl = &sfvt;
sf->mlpszFolder=NULL;
sf->mpSFParent=pParent;
TRACE(shell,"(%p)->(parent:%p, pidl=%p)\n",sf,pParent, pidl);
sf->pPidlMgr = PidlMgr_Constructor();
if (! sf->pPidlMgr )
{ HeapFree(GetProcessHeap(),0,sf);
ERR (shell,"-- Could not initialize PidMGR\n");
return NULL;
}
sf->mpidl = sf->pPidlMgr->lpvtbl->fnCopy(sf->pPidlMgr, pidl);
sf->mpidlNSRoot = NULL;
if(sf->mpidl)
{ /*if(sf->pPidlMgr->lpvtbl->fnIsDesktop(sf->pPidlMgr,sf->mpidl))
{ sf->pPidlMgr->lpvtbl->fnGetDesktop(sf->pPidlMgr,sf->mpidl);
}*/
dwSize = 0;
if(sf->mpSFParent->mlpszFolder)
{ dwSize += strlen(sf->mpSFParent->mlpszFolder) + 1;
}
dwSize += sf->pPidlMgr->lpvtbl->fnGetFolderText(sf->pPidlMgr,sf->mpidl,NULL,0);
sf->mlpszFolder = (LPSTR)HeapAlloc(GetProcessHeap(),0,dwSize);
if(sf->mlpszFolder)
{ *(sf->mlpszFolder) = 0;
if(sf->mpSFParent->mlpszFolder)
{ strcpy(sf->mlpszFolder, sf->mpSFParent->mlpszFolder);
wLen = strlen(sf->mlpszFolder);
if (wLen && sf->mlpszFolder[wLen-1]!='\\')
{ sf->mlpszFolder[wLen+0]='\\';
sf->mlpszFolder[wLen+1]='\0';
}
}
sf->pPidlMgr->lpvtbl->fnGetFolderText(sf->pPidlMgr, sf->mpidl, sf->mlpszFolder+strlen(sf->mlpszFolder), dwSize-strlen(sf->mlpszFolder));
}
}
TRACE(shell,"-- (%p)->(%p,%p)\n",sf,pParent, pidl);
return sf;
}
/**************************************************************************
* IShellFolder::QueryInterface
*/
static HRESULT WINAPI IShellFolder_QueryInterface(
LPSHELLFOLDER this, REFIID riid, LPVOID *ppvObj)
{ char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
{ *ppvObj = this;
}
else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
{ *ppvObj = (IShellFolder*)this;
}
if(*ppvObj)
{ (*(LPSHELLFOLDER*)ppvObj)->lpvtbl->fnAddRef(this);
TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE(shell,"-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* IShellFolder::AddRef
*/
static ULONG WINAPI IShellFolder_AddRef(LPSHELLFOLDER this)
{ TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
return ++(this->ref);
}
/**************************************************************************
* IShellFolder_Release
*/
static ULONG WINAPI IShellFolder_Release(LPSHELLFOLDER this)
{ TRACE(shell,"(%p)->(count=%lu)\n",this,this->ref);
if (!--(this->ref)) {
TRACE(shell,"-- destroying IShellFolder(%p)\n",this);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
/**************************************************************************
* IShellFolder_ParseDisplayName
*
* FIXME:
* pdwAttributes: not used
*/
static HRESULT WINAPI IShellFolder_ParseDisplayName(
LPSHELLFOLDER this,
HWND32 hwndOwner,
LPBC pbcReserved,
LPOLESTR32 lpszDisplayName, /* [in] name of file or folder*/
DWORD *pchEaten, /* [out] number of chars parsed*/
LPITEMIDLIST *ppidl, /* [out] the pidl*/
DWORD *pdwAttributes)
{ HRESULT hr=E_OUTOFMEMORY;
LPITEMIDLIST pidlFull=NULL;
DWORD dwChars=lstrlen32W(lpszDisplayName) + 1;
LPSTR pszTemp=(LPSTR)HeapAlloc(GetProcessHeap(),0,dwChars * sizeof(CHAR));
LPSTR pszNext=NULL;
CHAR szElement[MAX_PATH];
BOOL32 bType;
LPITEMIDLIST pidlTemp = NULL;
LPITEMIDLIST pidlOld = NULL;
TRACE(shell,"(%p)->(%x,%p,%p=%s,%p,pidl=%p,%p)\n",
this,hwndOwner,pbcReserved,lpszDisplayName,debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes
);
if(pszTemp)
{ hr = E_FAIL;
WideCharToLocal32(pszTemp, lpszDisplayName, dwChars);
if(*pszTemp)
{ pidlFull = this->pPidlMgr->lpvtbl->fnCreateDesktop(this->pPidlMgr);
/* check if the lpszDisplayName is Folder or File*/
bType = ! (GetFileAttributes32A(pszNext)&FILE_ATTRIBUTE_DIRECTORY);
pszNext = GetNextElement(pszTemp, szElement, MAX_PATH);
pidlTemp = this->pPidlMgr->lpvtbl->fnCreateDrive(this->pPidlMgr,szElement);
pidlOld = pidlFull;
pidlFull = this->pPidlMgr->lpvtbl->fnConcatenate(this->pPidlMgr,pidlFull,pidlTemp);
this->pPidlMgr->lpvtbl->fnDelete(this->pPidlMgr,pidlOld);
if(pidlFull)
{ while((pszNext=GetNextElement(pszNext, szElement, MAX_PATH)))
{ if(!*pszNext && bType)
{ pidlTemp = this->pPidlMgr->lpvtbl->fnCreateValue(this->pPidlMgr,szElement);
}
else
{ pidlTemp = this->pPidlMgr->lpvtbl->fnCreateFolder(this->pPidlMgr,szElement);
}
pidlOld = pidlFull;
pidlFull = this->pPidlMgr->lpvtbl->fnConcatenate(this->pPidlMgr,pidlFull,pidlTemp);
this->pPidlMgr->lpvtbl->fnDelete(this->pPidlMgr,pidlOld);
}
hr = S_OK;
}
}
HeapFree(GetProcessHeap(),0,pszTemp);
}
*ppidl = pidlFull;
return hr;
}
/**************************************************************************
* IShellFolder_EnumObjects
*/
static HRESULT WINAPI IShellFolder_EnumObjects(
LPSHELLFOLDER this,HWND32 hwndOwner,DWORD dwFlags,
LPENUMIDLIST* ppEnumIDList)
{ HRESULT hr;
TRACE(shell,"(%p)->(%x,%lx,%p)\n",this,hwndOwner,dwFlags,ppEnumIDList);
*ppEnumIDList = NULL;
*ppEnumIDList = IEnumIDList_Constructor (this->mlpszFolder, dwFlags, &hr);
TRACE(shell,"-- (%p)->(new ID List: %p)\n",this,*ppEnumIDList);
if(!*ppEnumIDList)
{ return hr;
}
return S_OK;
}
/**************************************************************************
* IShellFolder_Initialize()
* IPersistFolder Method
*/
static HRESULT WINAPI IShellFolder_Initialize(
LPSHELLFOLDER this,
LPCITEMIDLIST pidl)
{ TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
if(this->mpidlNSRoot)
{ this->pPidlMgr->lpvtbl->fnDelete(this->pPidlMgr, this->mpidlNSRoot);
this->mpidlNSRoot = NULL;
}
this->mpidlNSRoot = this->pPidlMgr->lpvtbl->fnCopy(this->pPidlMgr, pidl);
return S_OK;
}
/**************************************************************************
* IShellFolder_BindToObject
*/
static HRESULT WINAPI IShellFolder_BindToObject(
LPSHELLFOLDER this,
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
LPVOID * ppvOut)
{ char xclsid[50];
HRESULT hr;
LPSHELLFOLDER pShellFolder;
WINE_StringFromCLSID(riid,xclsid);
TRACE(shell,"(%p)->(pidl=%p,%p,\n\tSID:%s,%p)\n",this,pidl,pbcReserved,xclsid,ppvOut);
*ppvOut = NULL;
pShellFolder = IShellFolder_Constructor(this, pidl);
if(!pShellFolder)
return E_OUTOFMEMORY;
pShellFolder->lpvtbl->fnInitialize(pShellFolder, this->mpidlNSRoot);
hr = pShellFolder->lpvtbl->fnQueryInterface(pShellFolder, riid, ppvOut);
pShellFolder->lpvtbl->fnRelease(pShellFolder);
TRACE(shell,"-- (%p)->(interface=%p)\n",this, ppvOut);
return hr;
}
/**************************************************************************
* IShellFolder_BindToStorage
*/
static HRESULT WINAPI IShellFolder_BindToStorage(
LPSHELLFOLDER this,
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
LPVOID *ppvOut)
{ char xclsid[50];
WINE_StringFromCLSID(riid,xclsid);
FIXME(shell,"(%p)->(pidl=%p,%p,\n\tSID:%s,%p) stub\n",this,pidl,pbcReserved,xclsid,ppvOut);
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* IShellFolder_CompareIDs
*/
static HRESULT WINAPI IShellFolder_CompareIDs(
LPSHELLFOLDER this,
LPARAM lParam,
LPCITEMIDLIST pidl1,
LPCITEMIDLIST pidl2)
{ CHAR szString1[MAX_PATH] = "";
CHAR szString2[MAX_PATH] = "";
int nReturn;
LPCITEMIDLIST pidlTemp1 = pidl1, pidlTemp2 = pidl2;
TRACE(shell,"(%p)->(%lx,pidl1=%p,pidl2=%p) stub\n",this,lParam,pidl1,pidl2);
/*Special case - If one of the items is a Path and the other is a File, always
make the Path come before the File.*/
//get the last item in each list
while((this->pPidlMgr->lpvtbl->fnGetNextItem(this->pPidlMgr,pidlTemp1))->mkid.cb)
pidlTemp1 = this->pPidlMgr->lpvtbl->fnGetNextItem(this->pPidlMgr,pidlTemp1);
while((this->pPidlMgr->lpvtbl->fnGetNextItem(this->pPidlMgr,pidlTemp2))->mkid.cb)
pidlTemp2 = this->pPidlMgr->lpvtbl->fnGetNextItem(this->pPidlMgr,pidlTemp2);
//at this point, both pidlTemp1 and pidlTemp2 point to the last item in the list
if(this->pPidlMgr->lpvtbl->fnIsValue(this->pPidlMgr,pidlTemp1) != this->pPidlMgr->lpvtbl->fnIsValue(this->pPidlMgr,pidlTemp2))
{ if(this->pPidlMgr->lpvtbl->fnIsValue(this->pPidlMgr,pidlTemp1))
return 1;
return -1;
}
this->pPidlMgr->lpvtbl->fnGetDrive(this->pPidlMgr, pidl1,szString1,sizeof(szString1));
this->pPidlMgr->lpvtbl->fnGetDrive(this->pPidlMgr, pidl2,szString1,sizeof(szString2));
nReturn = strcasecmp(szString1, szString2);
if(nReturn)
return nReturn;
this->pPidlMgr->lpvtbl->fnGetFolderText(this->pPidlMgr, pidl1,szString1,sizeof(szString1));
this->pPidlMgr->lpvtbl->fnGetFolderText(this->pPidlMgr, pidl2,szString2,sizeof(szString2));
nReturn = strcasecmp(szString1, szString2);
if(nReturn)
return nReturn;
this->pPidlMgr->lpvtbl->fnGetValueText(this->pPidlMgr,pidl1,szString1,sizeof(szString1));
this->pPidlMgr->lpvtbl->fnGetValueText(this->pPidlMgr,pidl2,szString2,sizeof(szString2));
return strcasecmp(szString1, szString2);
}
/**************************************************************************
* IShellFolder_CreateViewObject
*/
static HRESULT WINAPI IShellFolder_CreateViewObject(
LPSHELLFOLDER this,HWND32 hwndOwner,REFIID riid,LPVOID *ppv)
{ char xclsid[50];
WINE_StringFromCLSID(riid,xclsid);
FIXME(shell,"(%p)->(0x%04x,\n\tIID:\t%s,%p),stub!\n",this,hwndOwner,xclsid,ppv);
*(DWORD*)ppv = 0;
return E_OUTOFMEMORY;
}
/**************************************************************************
* IShellFolder_GetAttributesOf
*/
static HRESULT WINAPI IShellFolder_GetAttributesOf(
LPSHELLFOLDER this,
UINT32 cidl,
LPCITEMIDLIST *apidl,
DWORD *rgfInOut)
{ FIXME(shell,"(%p)->(%d,%p,%p),stub!\n",this,cidl,apidl,rgfInOut);
return E_NOTIMPL;
}
/**************************************************************************
* IShellFolder_GetUIObjectOf
*/
static HRESULT WINAPI IShellFolder_GetUIObjectOf(
LPSHELLFOLDER this,
HWND32 hwndOwner,
UINT32 cidl,
LPCITEMIDLIST * apidl,
REFIID riid,
UINT32 * prgfInOut,
LPVOID * ppvOut)
{ char xclsid[50];
WINE_StringFromCLSID(riid,xclsid);
FIXME(shell,"(%p)->(%u %u,pidl=%p,\n\tIID:%s,%p,%p),stub!\n",
this,hwndOwner,cidl,apidl,xclsid,prgfInOut,ppvOut);
return E_FAIL;
}
/**************************************************************************
* IShellFolder_GetDisplayNameOf
*/
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
static HRESULT WINAPI IShellFolder_GetDisplayNameOf(
LPSHELLFOLDER this,
LPCITEMIDLIST pidl,
DWORD dwFlags,
LPSTRRET lpName)
{ CHAR szText[MAX_PATH];
int cchOleStr;
LPITEMIDLIST pidlTemp;
TRACE(shell,"(%p)->(pidl=%p,%lx,%p)\n",this,pidl,dwFlags,lpName);
switch(GET_SHGDN_RELATION(dwFlags))
{ case SHGDN_NORMAL:
//get the full name
this->pPidlMgr->lpvtbl->fnGetPidlPath(this->pPidlMgr, pidl, szText, sizeof(szText));
/* FIXME if the text is NULL and this is a value, then is something wrong*/
/* if(!*szText && this->pPidlMgr->lpvtbl->fnIsValue(this->pPidlMgr, this->pPidlMgr->lpvtbl->fnGetLastItem(this->pPidlMgr, pidl)))
{ do_something()
}*/
break;
case SHGDN_INFOLDER:
pidlTemp = this->pPidlMgr->lpvtbl->fnGetLastItem(this->pPidlMgr,pidl);
//get the relative name
this->pPidlMgr->lpvtbl->fnGetItemText(this->pPidlMgr, pidlTemp, szText, sizeof(szText));
/* FIXME if the text is NULL and this is a value, then is something wrong*/
if(!*szText && this->pPidlMgr->lpvtbl->fnIsValue(this->pPidlMgr,pidlTemp))
/* { do_something()
}*/
break;
default: return E_INVALIDARG;
}
//get the number of characters required
cchOleStr = strlen(szText) + 1;
TRACE(shell,"-- (%p)->(%s)\n",this,szText);
//allocate the wide character string
lpName->u.pOleStr = (LPWSTR)HeapAlloc(GetProcessHeap(),0,cchOleStr * sizeof(WCHAR));
if(!(lpName->u.pOleStr))
{ return E_OUTOFMEMORY;
}
lpName->uType = STRRET_WSTR;
LocalToWideChar32(lpName->u.pOleStr, szText, cchOleStr);
return S_OK;
}
/**************************************************************************
* IShellFolder_SetNameOf
*/
static HRESULT WINAPI IShellFolder_SetNameOf(
LPSHELLFOLDER this,
HWND32 hwndOwner,
LPCITEMIDLIST pidl,
LPCOLESTR32 lpName,
DWORD dw,
LPITEMIDLIST *pPidlOut)
{ FIXME(shell,"(%p)->(%u,pidl=%p,%s,%lu,%p),stub!\n",
this,hwndOwner,pidl,debugstr_w(lpName),dw,pPidlOut);
return E_NOTIMPL;
}
/**************************************************************************
* IShellLink_VTable
*/
static struct IShellLink_VTable slvt = {
(void *)1,
(void *)2,
(void *)3,
(void *)4,
(void *)5,
(void *)6,
(void *)7,
(void *)8,
(void *)9,
(void *)10,
(void *)11,
(void *)12,
(void *)13,
(void *)14,
(void *)15,
(void *)16,
(void *)17,
(void *)18,
(void *)19,
(void *)20,
(void *)21
};
/**************************************************************************
* IShellLink_Constructor
*/
LPSHELLLINK IShellLink_Constructor()
{ LPSHELLLINK sl;
sl = (LPSHELLLINK)HeapAlloc(GetProcessHeap(),0,sizeof(IShellLink));
sl->ref = 1;
sl->lpvtbl = &slvt;
TRACE(shell,"(%p)->()\n",sl);
return sl;
}
/**************************************************************************
* INTERNAL CLASS pidlmgr
*/
LPITEMIDLIST PidlMgr_CreateDesktop(LPPIDLMGR);
LPITEMIDLIST PidlMgr_CreateDrive(LPPIDLMGR,LPCSTR);
LPITEMIDLIST PidlMgr_CreateFolder(LPPIDLMGR,LPCSTR);
LPITEMIDLIST PidlMgr_CreateValue(LPPIDLMGR,LPCSTR);
void PidlMgr_Delete(LPPIDLMGR,LPITEMIDLIST);
LPITEMIDLIST PidlMgr_GetNextItem(LPPIDLMGR,LPITEMIDLIST);
LPITEMIDLIST PidlMgr_Copy(LPPIDLMGR,LPITEMIDLIST);
UINT16 PidlMgr_GetSize(LPPIDLMGR,LPITEMIDLIST);
BOOL32 PidlMgr_GetDesktop(LPPIDLMGR,LPCITEMIDLIST,LPSTR);
BOOL32 PidlMgr_GetDrive(LPPIDLMGR,LPCITEMIDLIST,LPSTR,UINT16);
LPITEMIDLIST PidlMgr_GetLastItem(LPPIDLMGR,LPCITEMIDLIST);
DWORD PidlMgr_GetItemText(LPPIDLMGR,LPCITEMIDLIST,LPSTR,UINT16);
BOOL32 PidlMgr_IsDesktop(LPPIDLMGR,LPCITEMIDLIST);
BOOL32 PidlMgr_IsDrive(LPPIDLMGR,LPCITEMIDLIST);
BOOL32 PidlMgr_IsFolder(LPPIDLMGR,LPCITEMIDLIST);
BOOL32 PidlMgr_IsValue(LPPIDLMGR,LPCITEMIDLIST);
BOOL32 PidlMgr_HasFolders(LPPIDLMGR,LPSTR,LPCITEMIDLIST);
DWORD PidlMgr_GetFolderText(LPPIDLMGR,LPCITEMIDLIST,LPSTR,DWORD);
DWORD PidlMgr_GetValueText(LPPIDLMGR,LPCITEMIDLIST,LPSTR,DWORD);
BOOL32 PidlMgr_GetValueType(LPPIDLMGR,LPCITEMIDLIST,LPCITEMIDLIST,LPDWORD);
DWORD PidlMgr_GetDataText(LPPIDLMGR,LPCITEMIDLIST,LPCITEMIDLIST,LPSTR,DWORD);
DWORD PidlMgr_GetPidlPath(LPPIDLMGR,LPCITEMIDLIST,LPSTR,DWORD);
LPITEMIDLIST PidlMgr_Concatenate(LPPIDLMGR,LPITEMIDLIST,LPITEMIDLIST);
LPITEMIDLIST PidlMgr_Create(LPPIDLMGR,PIDLTYPE,LPVOID,UINT16);
DWORD PidlMgr_GetData(LPPIDLMGR,PIDLTYPE,LPCITEMIDLIST,LPVOID,UINT16);
LPPIDLDATA PidlMgr_GetDataPointer(LPPIDLMGR,LPCITEMIDLIST);
BOOL32 PidlMgr_SeparatePathAndValue(LPPIDLMGR,LPITEMIDLIST,LPITEMIDLIST*,LPITEMIDLIST*);
static struct PidlMgr_VTable pmgrvt = {
PidlMgr_CreateDesktop,
PidlMgr_CreateDrive,
PidlMgr_CreateFolder,
PidlMgr_CreateValue,
PidlMgr_Delete,
PidlMgr_GetNextItem,
PidlMgr_Copy,
PidlMgr_GetSize,
PidlMgr_GetDesktop,
PidlMgr_GetDrive,
PidlMgr_GetLastItem,
PidlMgr_GetItemText,
PidlMgr_IsDesktop,
PidlMgr_IsDrive,
PidlMgr_IsFolder,
PidlMgr_IsValue,
PidlMgr_HasFolders,
PidlMgr_GetFolderText,
PidlMgr_GetValueText,
PidlMgr_GetValueType,
PidlMgr_GetDataText,
PidlMgr_GetPidlPath,
PidlMgr_Concatenate,
PidlMgr_Create,
PidlMgr_GetData,
PidlMgr_GetDataPointer,
PidlMgr_SeparatePathAndValue
};
/**************************************************************************
* PidlMgr_Constructor
*/
LPPIDLMGR PidlMgr_Constructor()
{ LPPIDLMGR pmgr;
pmgr = (LPPIDLMGR)HeapAlloc(GetProcessHeap(),0,sizeof(pidlmgr));
pmgr->lpvtbl = &pmgrvt;
TRACE(shell,"(%p)->()\n",pmgr);
/** FIXME DllRefCount++;*/
return pmgr;
}
/**************************************************************************
* PidlMgr_Destructor
*/
void PidlMgr_Destructor(LPPIDLMGR this)
{ HeapFree(GetProcessHeap(),0,this);
TRACE(shell,"(%p)->()\n",this);
/** FIXME DllRefCount--;*/
}
/**************************************************************************
* PidlMgr_CreateDesktop()
* PidlMgr_CreateDrive()
* PidlMgr_CreateFolder()
* PidlMgr_CreateValue()
*/
LPITEMIDLIST PidlMgr_CreateDesktop(LPPIDLMGR this)
{ TRACE(shell,"(%p)->()\n",this);
return PidlMgr_Create(this,PT_DESKTOP, (void *)"Desktop", sizeof("Desktop"));
}
LPITEMIDLIST PidlMgr_CreateDrive(LPPIDLMGR this, LPCSTR lpszNew)
{ TRACE(shell,"(%p)->(%s)\n",this,lpszNew);
return PidlMgr_Create(this,PT_DRIVE, (LPVOID)lpszNew , strlen(lpszNew)+1);
}
LPITEMIDLIST PidlMgr_CreateFolder(LPPIDLMGR this, LPCSTR lpszNew)
{ TRACE(shell,"(%p)->(%s)\n",this,lpszNew);
return PidlMgr_Create(this,PT_FOLDER, (LPVOID)lpszNew, strlen(lpszNew)+1);
}
LPITEMIDLIST PidlMgr_CreateValue(LPPIDLMGR this,LPCSTR lpszNew)
{ TRACE(shell,"(%p)->(%s)\n",this,lpszNew);
return PidlMgr_Create(this,PT_VALUE, (LPVOID)lpszNew, strlen(lpszNew)+1);
}
/**************************************************************************
* PidlMgr_Delete()
* Deletes a PIDL
*/
void PidlMgr_Delete(LPPIDLMGR this,LPITEMIDLIST pidl)
{ TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
HeapFree(GetProcessHeap(),0,pidl);
}
/**************************************************************************
* PidlMgr_GetNextItem()
*/
LPITEMIDLIST PidlMgr_GetNextItem(LPPIDLMGR this, LPITEMIDLIST pidl)
{ TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
if(pidl)
{ return (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
}
else
{ return (NULL);
}
}
/**************************************************************************
* PidlMgr_Copy()
*/
LPITEMIDLIST PidlMgr_Copy(LPPIDLMGR this, LPITEMIDLIST pidlSource)
{ LPITEMIDLIST pidlTarget = NULL;
UINT16 cbSource = 0;
TRACE(shell,"-- (%p)->(pidl=%p)\n",this,pidlSource);
if(NULL == pidlSource)
{ ERR(shell,"-- (%p)->(%p)\n",this,pidlSource);
return (NULL);
}
cbSource = PidlMgr_GetSize(this, pidlSource);
pidlTarget = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,cbSource);
if(!pidlTarget)
{ return (NULL);
}
memcpy(pidlTarget, pidlSource, cbSource);
TRACE(shell,"-- (%p)->(pidl=%p to new pidl=%p)\n",this,pidlSource,pidlTarget);
return pidlTarget;
}
/**************************************************************************
* PidlMgr_GetSize()
* calculates the size of the complete pidl
*/
UINT16 PidlMgr_GetSize(LPPIDLMGR this, LPITEMIDLIST pidl)
{ UINT16 cbTotal = 0;
LPITEMIDLIST pidlTemp = pidl;
TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
if(pidlTemp)
{ while(pidlTemp->mkid.cb)
{ cbTotal += pidlTemp->mkid.cb;
pidlTemp = PidlMgr_GetNextItem(this, pidlTemp);
}
//add the size of the NULL terminating ITEMIDLIST
cbTotal += sizeof(ITEMIDLIST);
}
TRACE(shell,"-- size %u\n",cbTotal);
return (cbTotal);
}
/**************************************************************************
* PidlMgr_GetDesktop()
*
* FIXME: quick hack
*/
BOOL32 PidlMgr_GetDesktop(LPPIDLMGR this,LPCITEMIDLIST pidl,LPSTR pOut)
{ TRACE(shell,"(%p)->(%p %p)\n",this,pidl,pOut);
return (BOOL32)PidlMgr_GetData(this,PT_DESKTOP, pidl, (LPVOID)pOut, 255);
}
/**************************************************************************
* PidlMgr_GetDrive()
*
* FIXME: quick hack
*/
BOOL32 PidlMgr_GetDrive(LPPIDLMGR this,LPCITEMIDLIST pidl,LPSTR pOut, UINT16 uSize)
{ LPITEMIDLIST pidlTemp=NULL;
TRACE(shell,"(%p)->(%p,%p,%u)\n",this,pidl,pOut,uSize);
if(PidlMgr_IsDesktop(this,pidl))
{ pidlTemp = PidlMgr_GetNextItem(this,pidl);
}
else if (PidlMgr_IsDrive(this,pidl))
{ pidlTemp = PidlMgr_GetNextItem(this,pidl);
return (BOOL32)PidlMgr_GetData(this,PT_DRIVE, pidlTemp, (LPVOID)pOut, uSize);
}
return FALSE;
}
/**************************************************************************
* PidlMgr_GetLastItem()
* Gets the last item in the list
*/
LPITEMIDLIST PidlMgr_GetLastItem(LPPIDLMGR this,LPCITEMIDLIST pidl)
{ LPITEMIDLIST pidlLast = NULL;
TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
if(pidl)
{ while(pidl->mkid.cb)
{ pidlLast = (LPITEMIDLIST)pidl;
pidl = PidlMgr_GetNextItem(this,pidl);
}
}
return pidlLast;
}
/**************************************************************************
* PidlMgr_GetItemText()
* Gets the text for only this item
*/
DWORD PidlMgr_GetItemText(LPPIDLMGR this,LPCITEMIDLIST pidl, LPSTR lpszText, UINT16 uSize)
{ TRACE(shell,"(%p)->(pidl=%p %p %x)\n",this,pidl,lpszText,uSize);
if (PidlMgr_IsDesktop(this, pidl))
{ return PidlMgr_GetData(this,PT_DESKTOP, pidl, (LPVOID)lpszText, uSize);
}
if (PidlMgr_IsDrive(this, pidl))
{ return PidlMgr_GetData(this,PT_DRIVE, pidl, (LPVOID)lpszText, uSize);
}
return PidlMgr_GetData(this,PT_TEXT, pidl, (LPVOID)lpszText, uSize);
}
/**************************************************************************
* PidlMgr_IsDesktop()
* PidlMgr_IsDrive()
* PidlMgr_IsFolder()
* PidlMgr_IsValue()
*/
BOOL32 PidlMgr_IsDesktop(LPPIDLMGR this,LPCITEMIDLIST pidl)
{ LPPIDLDATA pData;
TRACE(shell,"%p->(%p)\n",this,pidl);
pData = PidlMgr_GetDataPointer(this,pidl);
return (PT_DESKTOP == pData->type);
}
BOOL32 PidlMgr_IsDrive(LPPIDLMGR this,LPCITEMIDLIST pidl)
{ LPPIDLDATA pData;
TRACE(shell,"%p->(%p)\n",this,pidl);
pData = PidlMgr_GetDataPointer(this,pidl);
return (PT_DRIVE == pData->type);
}
BOOL32 PidlMgr_IsFolder(LPPIDLMGR this,LPCITEMIDLIST pidl)
{ LPPIDLDATA pData;
TRACE(shell,"%p->(%p)\n",this,pidl);
pData = PidlMgr_GetDataPointer(this,pidl);
return (PT_FOLDER == pData->type);
}
BOOL32 PidlMgr_IsValue(LPPIDLMGR this,LPCITEMIDLIST pidl)
{ LPPIDLDATA pData;
TRACE(shell,"%p->(%p)\n",this,pidl);
pData = PidlMgr_GetDataPointer(this,pidl);
return (PT_VALUE == pData->type);
}
/**************************************************************************
* PidlMgr_HasFolders()
* fixme: quick hack
*/
BOOL32 PidlMgr_HasFolders(LPPIDLMGR this, LPSTR pszPath, LPCITEMIDLIST pidl)
{ BOOL32 bResult= FALSE;
WIN32_FIND_DATA32A stffile;
HANDLE32 hFile;
TRACE (shell,"(%p)->%p %p\n",this, pszPath, pidl);
hFile = FindFirstFile32A(pszPath,&stffile);
do
{ if (! (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{ bResult= TRUE;
}
} while( FindNextFile32A(hFile,&stffile));
FindClose32 (hFile);
return bResult;
}
/**************************************************************************
* PidlMgr_GetFolderText()
* Creates a Path string from a PIDL, filtering out the Desktop and the Drive
* value, if either is present.
*/
DWORD PidlMgr_GetFolderText(LPPIDLMGR this,LPCITEMIDLIST pidl,
LPSTR lpszPath, DWORD dwSize)
{ LPITEMIDLIST pidlTemp;
DWORD dwCopied = 0;
TRACE(shell,"(%p)->(%p)\n",this,pidl);
if(!pidl)
{ return 0;
}
if(PidlMgr_IsDesktop(this,pidl))
{ pidlTemp = PidlMgr_GetNextItem(this,pidl);
}
else if (PidlMgr_IsFolder(this,pidl))
{ pidlTemp = PidlMgr_GetNextItem(this,pidl);
}
else
{ pidlTemp = (LPITEMIDLIST)pidl;
}
//if this is NULL, return the required size of the buffer
if(!lpszPath)
{ while(pidlTemp->mkid.cb)
{ LPPIDLDATA pData = PidlMgr_GetDataPointer(this,pidlTemp);
//add the length of this item plus one for the backslash
dwCopied += strlen(pData->szText) + 1; /* fixme pData->szText is not every time a string*/
pidlTemp = PidlMgr_GetNextItem(this,pidlTemp);
}
//add one for the NULL terminator
return dwCopied + 1;
}
*lpszPath = 0;
while(pidlTemp->mkid.cb && (dwCopied < dwSize))
{ LPPIDLDATA pData = PidlMgr_GetDataPointer(this,pidlTemp);
//if this item is a value, then skip it and finish
if(PT_VALUE == pData->type)
{ break;
}
strcat(lpszPath, pData->szText);
strcat(lpszPath, "\\");
dwCopied += strlen(pData->szText) + 1;
pidlTemp = PidlMgr_GetNextItem(this,pidlTemp);
}
//remove the last backslash if necessary
if(dwCopied)
{ if(*(lpszPath + strlen(lpszPath) - 1) == '\\')
{ *(lpszPath + strlen(lpszPath) - 1) = 0;
dwCopied--;
}
}
return dwCopied;
}
/**************************************************************************
* PidlMgr_GetValueText()
* Gets the text for the last item in the list
*/
DWORD PidlMgr_GetValueText(LPPIDLMGR this,
LPCITEMIDLIST pidl, LPSTR lpszValue, DWORD dwSize)
{ LPITEMIDLIST pidlTemp=pidl;
CHAR szText[MAX_PATH];
TRACE(shell,"(%p)->(pidl=%p %p %lx)\n",this,pidl,lpszValue,dwSize);
if(!pidl)
{ return 0;
}
while(pidlTemp->mkid.cb && !PidlMgr_IsValue(this,pidlTemp))
{ pidlTemp = PidlMgr_GetNextItem(this,pidlTemp);
}
if(!pidlTemp->mkid.cb)
{ return 0;
}
PidlMgr_GetItemText(this, pidlTemp, szText, sizeof(szText));
if(!lpszValue)
{ return strlen(szText) + 1;
}
strcpy(lpszValue, szText);
TRACE(shell,"-- (%p)->(pidl=%p %p=%s %lx)\n",this,pidl,lpszValue,lpszValue,dwSize);
return strlen(lpszValue);
}
/**************************************************************************
* PidlMgr_GetValueType()
*/
BOOL32 PidlMgr_GetValueType( LPPIDLMGR this,
LPCITEMIDLIST pidlPath, LPCITEMIDLIST pidlValue, LPDWORD pdwType)
{ LPSTR lpszFolder,
lpszValueName;
DWORD dwNameSize;
FIXME(shell,"(%p)->(%p %p %p) stub\n",this,pidlPath,pidlValue,pdwType);
if(!pidlPath)
{ return FALSE;
}
if(!pidlValue)
{ return FALSE;
}
if(!pdwType)
{ return FALSE;
}
//get the Desktop
//PidlMgr_GetDesktop(this,pidlPath);
/* fixme: add the driveletter here*/
//assemble the Folder string
dwNameSize = PidlMgr_GetFolderText(this,pidlPath, NULL, 0);
lpszFolder = (LPSTR)HeapAlloc(GetProcessHeap(),0,dwNameSize);
if(!lpszFolder)
{ return FALSE;
}
PidlMgr_GetFolderText(this,pidlPath, lpszFolder, dwNameSize);
//assemble the value name
dwNameSize = PidlMgr_GetValueText(this,pidlValue, NULL, 0);
lpszValueName = (LPSTR)HeapAlloc(GetProcessHeap(),0,dwNameSize);
if(!lpszValueName)
{ HeapFree(GetProcessHeap(),0,lpszFolder);
return FALSE;
}
PidlMgr_GetValueText(this,pidlValue, lpszValueName, dwNameSize);
/* fixme: we've got the path now do something with it
-like get the filetype*/
pdwType=NULL;
HeapFree(GetProcessHeap(),0,lpszFolder);
HeapFree(GetProcessHeap(),0,lpszValueName);
return TRUE;
}
/**************************************************************************
* PidlMgr_GetDataText()
*/
DWORD PidlMgr_GetDataText( LPPIDLMGR this,
LPCITEMIDLIST pidlPath, LPCITEMIDLIST pidlValue, LPSTR lpszOut, DWORD dwOutSize)
{ LPSTR lpszFolder,
lpszValueName;
DWORD dwNameSize;
FIXME(shell,"(%p)->(pidl=%p pidl=%p) stub\n",this,pidlPath,pidlValue);
if(!lpszOut)
{ return FALSE;
}
if(!pidlPath)
{ return FALSE;
}
if(!pidlValue)
{ return FALSE;
}
/* fixme: get the driveletter*/
//assemble the Folder string
dwNameSize = PidlMgr_GetFolderText(this,pidlPath, NULL, 0);
lpszFolder = (LPSTR)HeapAlloc(GetProcessHeap(),0,dwNameSize);
if(!lpszFolder)
{ return FALSE;
}
PidlMgr_GetFolderText(this,pidlPath, lpszFolder, dwNameSize);
//assemble the value name
dwNameSize = PidlMgr_GetValueText(this,pidlValue, NULL, 0);
lpszValueName = (LPSTR)HeapAlloc(GetProcessHeap(),0,dwNameSize);
if(!lpszValueName)
{ HeapFree(GetProcessHeap(),0,lpszFolder);
return FALSE;
}
PidlMgr_GetValueText(this,pidlValue, lpszValueName, dwNameSize);
/* fixme: we've got the path now do something with it*/
HeapFree(GetProcessHeap(),0,lpszFolder);
HeapFree(GetProcessHeap(),0,lpszValueName);
TRACE(shell,"-- (%p)->(%p=%s %lx)\n",this,lpszOut,lpszOut,dwOutSize);
return TRUE;
}
/**************************************************************************
* CPidlMgr::GetPidlPath()
* Create a string that includes the Drive name, the folder text and
* the value text.
*/
DWORD PidlMgr_GetPidlPath(LPPIDLMGR this,
LPCITEMIDLIST pidl, LPSTR lpszOut, DWORD dwOutSize)
{ LPSTR lpszTemp;
WORD len;
TRACE(shell,"(%p)->(%p,%lu)\n",this,lpszOut,dwOutSize);
if(!lpszOut)
{ return 0;
}
*lpszOut = 0;
lpszTemp = lpszOut;
dwOutSize -= PidlMgr_GetFolderText(this,pidl, lpszTemp, dwOutSize);
//add a backslash if necessary
len = strlen(lpszTemp);
if (len && lpszTemp[len-1]!='\\')
{ lpszTemp[len+0]='\\';
lpszTemp[len+1]='\0';
dwOutSize--;
}
lpszTemp = lpszOut + strlen(lpszOut);
//add the value string
PidlMgr_GetValueText(this,pidl, lpszTemp, dwOutSize);
//remove the last backslash if necessary
if(*(lpszOut + strlen(lpszOut) - 1) == '\\')
{ *(lpszOut + strlen(lpszOut) - 1) = 0;
}
TRACE(shell,"-- (%p)->(%p=%s,%lu)\n",this,lpszOut,lpszOut,dwOutSize);
return strlen(lpszOut);
}
/**************************************************************************
* PidlMgr_Concatenate()
* Create a new PIDL by combining two existing PIDLs.
*/
LPITEMIDLIST PidlMgr_Concatenate(LPPIDLMGR this,LPITEMIDLIST pidl1, LPITEMIDLIST pidl2)
{ LPITEMIDLIST pidlNew;
UINT32 cb1 = 0, cb2 = 0;
TRACE(shell,"(%p)->(%p,%p)\n",this,pidl1,pidl2);
if(!pidl1 && !pidl2)
{ return NULL;
}
if(!pidl1)
{ pidlNew = PidlMgr_Copy(this,pidl2);
return pidlNew;
}
if(!pidl2)
{ pidlNew = PidlMgr_Copy(this,pidl1);
return pidlNew;
}
cb1 = PidlMgr_GetSize(this,pidl1) - sizeof(ITEMIDLIST);
cb2 = PidlMgr_GetSize(this,pidl2);
pidlNew = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,cb1+cb2);
if(pidlNew)
{ memcpy(pidlNew, pidl1, cb1);
memcpy(((LPBYTE)pidlNew) + cb1, pidl2, cb2);
}
TRACE(shell,"-- (%p)-> (new pidl=%p)\n",this,pidlNew);
return pidlNew;
}
/**************************************************************************
* PidlMgr_Create()
* Creates a new PIDL
* type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
* pIn = data
* uInSize = size of data
*/
LPITEMIDLIST PidlMgr_Create(LPPIDLMGR this,PIDLTYPE type, LPVOID pIn, UINT16 uInSize)
{ LPITEMIDLIST pidlOut=NULL;
UINT16 uSize;
LPITEMIDLIST pidlTemp=NULL;
LPPIDLDATA pData;
TRACE(shell,"(%p)->(%x %p %x)\n",this,type,pIn,uInSize);
if (! pIn)
{ return NULL;
}
uSize = sizeof(ITEMIDLIST) + (sizeof(PIDLTYPE)) + uInSize;
/* Allocate the memory, adding an additional ITEMIDLIST for the NULL terminating
ID List. */
pidlOut = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,uSize + sizeof(ITEMIDLIST));
pidlTemp = pidlOut;
if(pidlOut)
{ pidlTemp->mkid.cb = uSize;
pData = PidlMgr_GetDataPointer(this,pidlTemp);
pData->type = type;
switch(type)
{ case PT_DESKTOP: memcpy(pData->szText, pIn, uInSize);
TRACE(shell,"-- (%p)->create Desktop: %s\n",this,debugstr_a(pData->szText));
break;
case PT_DRIVE: memcpy(pData->szText, pIn, uInSize);
TRACE(shell,"-- (%p)->create Drive: %s\n",this,debugstr_a(pData->szText));
break;
case PT_FOLDER:
case PT_VALUE: memcpy(pData->szText, pIn, uInSize);
TRACE(shell,"-- (%p)->create Value: %s\n",this,debugstr_a(pData->szText));
break;
default: FIXME(shell,"-- (%p) wrong argument\n",this);
break;
}
pidlTemp = PidlMgr_GetNextItem(this,pidlTemp);
pidlTemp->mkid.cb = 0;
pidlTemp->mkid.abID[0] = 0;
}
TRACE(shell,"-- (%p)->(pidl=%p)\n",this,pidlOut);
return pidlOut;
}
/**************************************************************************
* PidlMgr_GetData(PIDLTYPE, LPCITEMIDLIST, LPVOID, UINT16)
*/
DWORD PidlMgr_GetData(
LPPIDLMGR this,
PIDLTYPE type,
LPCITEMIDLIST pidl,
LPVOID pOut,
UINT16 uOutSize)
{ LPPIDLDATA pData;
DWORD dwReturn=0;
TRACE(shell,"(%p)->(%x %p %p %x)\n",this,type,pidl,pOut,uOutSize);
if(!pidl)
{ return 0;
}
pData = PidlMgr_GetDataPointer(this,pidl);
//copy the data
switch(type)
{ case PT_DESKTOP: if(uOutSize < 1)
return 0;
if(PT_DESKTOP != pData->type)
return 0;
*(LPSTR)pOut = 0;
strncpy((LPSTR)pOut, "DESKTOP", uOutSize);
dwReturn = strlen((LPSTR)pOut);
break;
case PT_DRIVE: if(uOutSize < 1)
return 0;
if(PT_DESKTOP != pData->type)
return 0;
*(LPSTR)pOut = 0;
strncpy((LPSTR)pOut, "DRIVE", uOutSize);
dwReturn = strlen((LPSTR)pOut);
break;
case PT_FOLDER:
case PT_VALUE:
case PT_TEXT: *(LPSTR)pOut = 0;
strncpy((LPSTR)pOut, pData->szText, uOutSize);
dwReturn = strlen((LPSTR)pOut);
break;
}
TRACE(shell,"-- (%p)->(%p:%s %lx)\n",this,pOut,(char*)pOut,dwReturn);
return dwReturn;
}
/**************************************************************************
* PidlMgr_GetDataPointer()
*/
LPPIDLDATA PidlMgr_GetDataPointer(LPPIDLMGR this,LPITEMIDLIST pidl)
{ if(!pidl)
{ return NULL;
}
TRACE (shell,"(%p)->(%p)\n" ,this, pidl);
return (LPPIDLDATA)(pidl->mkid.abID);
}
/**************************************************************************
* CPidlMgr_SeparatePathAndValue)
* Creates a separate path and value PIDL from a fully qualified PIDL.
*/
BOOL32 PidlMgr_SeparatePathAndValue(LPPIDLMGR this,
LPITEMIDLIST pidlFQ, LPITEMIDLIST *ppidlPath, LPITEMIDLIST *ppidlValue)
{ LPITEMIDLIST pidlTemp;
TRACE (shell,"(%p)->(pidl=%p pidl=%p pidl=%p)",this,pidlFQ,ppidlPath,ppidlValue);
if(!pidlFQ)
{ return FALSE;
}
*ppidlValue = PidlMgr_GetLastItem(this,pidlFQ);
if(!PidlMgr_IsValue(this,*ppidlValue))
{ return FALSE;
}
*ppidlValue = PidlMgr_Copy(this,*ppidlValue);
*ppidlPath = PidlMgr_Copy(this,pidlFQ);
pidlTemp = PidlMgr_GetLastItem(this,*ppidlPath);
pidlTemp->mkid.cb = 0;
pidlTemp->mkid.abID[0] = 0;
return TRUE;
}