blob: 3ddde1108b5ef9b16775ef4eca4b0a2c748b6a4c [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, 980801>
*/
#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"
#include "winproc.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)
*
* 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
*/
LPSTR GetNextElement(LPSTR pszNext,LPSTR pszOut,DWORD dwOut)
{ LPSTR pszTail = pszNext;
DWORD dwCopy;
TRACE(shell,"(%s %p 0x%08lx)\n",debugstr_a(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 0x%08lx)\n",debugstr_a(pszNext),debugstr_a(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)
{ IUnknown *pObj = NULL;
HRESULT hres;
char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE(shell,"%p->(%p,\n\tIID:\t%s,%p)\n",this,pUnknown,xriid,ppObject);
*ppObject = NULL;
if(pUnknown)
{ return(CLASS_E_NOAGGREGATION);
}
if (IsEqualIID(riid, &IID_IShellFolder))
{ pObj = (IUnknown *)IShellFolder_Constructor(NULL,NULL);
}
else if (IsEqualIID(riid, &IID_IShellView))
{ pObj = (IUnknown *)IShellView_Constructor();
}
else if (IsEqualIID(riid, &IID_IShellLink))
{ pObj = (IUnknown *)IShellLink_Constructor();
}
else
{ ERR(shell,"unknown IID requested\n\tIID:\t%s\n",xriid);
return(E_NOINTERFACE);
}
if (!pObj)
{ return(E_OUTOFMEMORY);
}
hres = pObj->lpvtbl->fnQueryInterface(pObj,riid, ppObject);
pObj->lpvtbl->fnRelease(pObj);
TRACE(shell,"-- Object created: (%p)->%p\n",this,*ppObject);
return hres;
}
/******************************************************************************
* IClassFactory_LockServer
*/
static HRESULT WINAPI IClassFactory_LockServer(LPCLASSFACTORY this, BOOL32 fLock)
{ TRACE(shell,"%p->(0x%x), not implemented\n",this, fLock);
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 0x%08lx %p)\n",lpeidl,debugstr_a(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);
/* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's
subsystems actually use it (and so may a third party browser)
*/
if(pceltFetched)
*pceltFetched = 0;
*rgelt=0;
if(celt > 1 && !pceltFetched)
{ return E_INVALIDARG;
}
for(i = 0; i < celt; i++)
{ if(!(this->mpCurrent))
{ hr = S_FALSE;
break;
}
temp = ILClone(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;
DWORD dwDrivemap;
CHAR szDriveName[4];
CHAR szPath[MAX_PATH];
TRACE(shell,"(%p)->(%s 0x%08lx) \n",this,debugstr_a(lpszPath),dwFlags);
if (lpszPath && lpszPath[0]!='\0')
{ strcpy(szPath, lpszPath);
PathAddBackslash(szPath);
strcat(szPath,"*.*");
}
/*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)
{ TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS (special) items\n",this);
//create the pidl for this item
pidl = this->mpPidlMgr->lpvtbl->fnCreateMyComputer(this->mpPidlMgr);
if(pidl)
{ if(!IEnumIDList_AddToEnumList(this, pidl))
return FALSE;
}
}
else if (lpszPath[0]=='\0') /* enumerate the drives*/
{ TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS (drives)\n",this);
dwDrivemap = GetLogicalDrives();
strcpy (szDriveName,"A:\\");
while (szDriveName[0]<='Z')
{ if(dwDrivemap & 0x00000001L)
{ pidl = this->mpPidlMgr->lpvtbl->fnCreateDrive(this->mpPidlMgr,szDriveName );
if(pidl)
{ if(!IEnumIDList_AddToEnumList(this, pidl))
return FALSE;
}
}
szDriveName[0]++;
dwDrivemap = dwDrivemap >> 1;
}
}
else
{ TRACE (shell,"-- (%p)-> enumerate SHCONTF_FOLDERS of %s\n",this,debugstr_a(szPath));
hFile = FindFirstFile32A(szPath,&stffile);
if ( hFile != INVALID_HANDLE_VALUE32 )
{ do
{ if ( (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp (stffile.cFileName, ".") && strcmp (stffile.cFileName, ".."))
{ 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)
{ if(lpszPath)
{ TRACE (shell,"-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",this,debugstr_a(szPath));
hFile = FindFirstFile32A(szPath,&stffile);
if ( hFile != INVALID_HANDLE_VALUE32 )
{ do
{ if (! (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{ pidl = this->mpPidlMgr->lpvtbl->fnCreateValue(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;
SHFree(pDelete->pidl);
SHFree(pDelete);
}
this->mpFirst = this->mpLast = this->mpCurrent = NULL;
return TRUE;
}
/***********************************************************************
* IShellView implementation
*/
static HRESULT WINAPI IShellView_QueryInterface(LPSHELLVIEW,REFIID riid, LPVOID *ppvObj);
static ULONG WINAPI IShellView_AddRef(LPSHELLVIEW) ;
static ULONG WINAPI IShellView_Release(LPSHELLVIEW);
// *** IOleWindow methods ***
static HRESULT WINAPI IShellView_GetWindow(LPSHELLVIEW,HWND32 * lphwnd);
static HRESULT WINAPI IShellView_ContextSensitiveHelp(LPSHELLVIEW,BOOL32 fEnterMode);
// *** IShellView methods ***
static HRESULT WINAPI IShellView_TranslateAccelerator(LPSHELLVIEW,LPMSG32 lpmsg);
static HRESULT WINAPI IShellView_EnableModeless(LPSHELLVIEW,BOOL32 fEnable);
static HRESULT WINAPI IShellView_UIActivate(LPSHELLVIEW,UINT32 uState);
static HRESULT WINAPI IShellView_Refresh(LPSHELLVIEW);
static HRESULT WINAPI IShellView_CreateViewWindow(LPSHELLVIEW, IShellView *lpPrevView,LPCFOLDERSETTINGS lpfs, IShellBrowser * psb,RECT32 * prcView, HWND32 *phWnd);
static HRESULT WINAPI IShellView_DestroyViewWindow(LPSHELLVIEW);
static HRESULT WINAPI IShellView_GetCurrentInfo(LPSHELLVIEW, LPFOLDERSETTINGS lpfs);
static HRESULT WINAPI IShellView_AddPropertySheetPages(LPSHELLVIEW, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam);
static HRESULT WINAPI IShellView_SaveViewState(LPSHELLVIEW);
static HRESULT WINAPI IShellView_SelectItem(LPSHELLVIEW, LPCITEMIDLIST pidlItem, UINT32 uFlags);
static HRESULT WINAPI IShellView_GetItemObject(LPSHELLVIEW, UINT32 uItem, REFIID riid,LPVOID *ppv);
static struct IShellView_VTable svvt =
{ IShellView_QueryInterface,
IShellView_AddRef,
IShellView_Release,
IShellView_GetWindow,
IShellView_ContextSensitiveHelp,
IShellView_TranslateAccelerator,
IShellView_EnableModeless,
IShellView_UIActivate,
IShellView_Refresh,
IShellView_CreateViewWindow,
IShellView_DestroyViewWindow,
IShellView_GetCurrentInfo,
IShellView_AddPropertySheetPages,
IShellView_SaveViewState,
IShellView_SelectItem,
IShellView_GetItemObject
};
/**************************************************************************
* IShellView_Constructor
*/
LPSHELLVIEW IShellView_Constructor(LPSHELLFOLDER pFolder, LPCITEMIDLIST pidl)
{ LPSHELLVIEW sv;
sv=(LPSHELLVIEW)HeapAlloc(GetProcessHeap(),0,sizeof(IShellView));
sv->ref=1;
sv->lpvtbl=&svvt;
sv->mpidl = ILClone(pidl);
sv->pSFParent = pFolder;
if(sv->pSFParent)
sv->pSFParent->lpvtbl->fnAddRef(sv->pSFParent);
TRACE(shell,"(%p)->(%p pidl=%p)\n",sv, pFolder, pidl);
return sv;
}
/**************************************************************************
* ShellView_WndProc
*/
LRESULT CALLBACK ShellView_WndProc(HWND32 hWnd, UINT32 uMessage, WPARAM32 wParam, LPARAM lParam)
{ LPSHELLVIEW pThis = (LPSHELLVIEW)GetWindowLong32A(hWnd, GWL_USERDATA);
LPCREATESTRUCT32A lpcs;
FIXME(shell,"(hwnd=%x msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
switch (uMessage)
{ case WM_NCCREATE:
{ TRACE(shell,"WM_NCCREATE\n");
lpcs = (LPCREATESTRUCT32A)lParam;
pThis = (LPSHELLVIEW)(lpcs->lpCreateParams);
SetWindowLong32A(hWnd, GWL_USERDATA, (LONG)pThis);
//set the window handle
pThis->hWnd = hWnd;
}
break;
case WM_SIZE:
TRACE(shell,"WM_SIZE\n");
return FALSE;
case WM_CREATE:
TRACE(shell,"WM_CREATE\n");
return FALSE;
case WM_SETFOCUS:
TRACE(shell,"WM_SETFOCUS\n");
return FALSE;
case WM_KILLFOCUS:
TRACE(shell,"WM_KILLFOCUS\n");
return FALSE;
case WM_ACTIVATE:
TRACE(shell,"WM_ACTIVATE\n");
return FALSE;
case WM_COMMAND:
TRACE(shell,"WM_COMMAND\n");
return FALSE;
case WM_INITMENUPOPUP:
TRACE(shell,"WM_INITMENUPOPUP\n");
return FALSE;
case WM_NOTIFY:
TRACE(shell,"WM_NOTIFY\n");
return FALSE;
/* case WM_SETTINGCHANGE:
return FALSE;*/
}
return DefWindowProc32A (hWnd, uMessage, wParam, lParam);
}
/**************************************************************************
* IShellView::QueryInterface
*/
static HRESULT WINAPI IShellView_QueryInterface(LPSHELLVIEW 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_IShellView)) /*IShellView*/
{ *ppvObj = (IShellView*)this;
}
if(*ppvObj)
{ (*(LPSHELLVIEW*)ppvObj)->lpvtbl->fnAddRef(this);
TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE(shell,"-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* IShellView::AddRef
*/
static ULONG WINAPI IShellView_AddRef(LPSHELLVIEW this)
{ TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
return ++(this->ref);
}
/**************************************************************************
* IShellView::Release
*/
static ULONG WINAPI IShellView_Release(LPSHELLVIEW this)
{ TRACE(shell,"(%p)->()\n",this);
if (!--(this->ref))
{ TRACE(shell," destroying IEnumIDList(%p)\n",this);
if(this->pSFParent)
this->pSFParent->lpvtbl->fnRelease(this->pSFParent);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
/**************************************************************************
* IShellView::GetWindow
*/
static HRESULT WINAPI IShellView_GetWindow(LPSHELLVIEW this,HWND32 * phWnd)
{ TRACE(shell,"(%p) stub\n",this);
*phWnd = this->hWnd;
return S_OK;
}
static HRESULT WINAPI IShellView_ContextSensitiveHelp(LPSHELLVIEW this,BOOL32 fEnterMode)
{ FIXME(shell,"(%p) stub\n",this);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellView_TranslateAccelerator(LPSHELLVIEW this,LPMSG32 lpmsg)
{ FIXME(shell,"(%p)->(%p) stub\n",this,lpmsg);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellView_EnableModeless(LPSHELLVIEW this,BOOL32 fEnable)
{ FIXME(shell,"(%p) stub\n",this);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellView_UIActivate(LPSHELLVIEW this,UINT32 uState)
{ FIXME(shell,"(%p) stub\n",this);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellView_Refresh(LPSHELLVIEW this)
{ FIXME(shell,"(%p) stub\n",this);
return S_OK;
}
static HRESULT WINAPI IShellView_CreateViewWindow(LPSHELLVIEW this, IShellView *lpPrevView,
LPCFOLDERSETTINGS lpfs, IShellBrowser * psb,RECT32 * prcView, HWND32 *phWnd)
{ WNDCLASS32A wc;
*phWnd = 0;
TRACE(shell,"(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",this, lpPrevView,lpfs, psb, prcView, phWnd);
//if our window class has not been registered, then do so
if(!GetClassInfo32A(shell32_hInstance, SV_CLASS_NAME, &wc))
{ ZeroMemory(&wc, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC32) ShellView_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = shell32_hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor32A (0, IDC_ARROW32A);
wc.hbrBackground = (HBRUSH32)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = SV_CLASS_NAME;
if(!RegisterClass32A(&wc))
return E_FAIL;
}
//set up the member variables
this->pShellBrowser = psb;
this->FolderSettings = *lpfs;
//get our parent window
this->pShellBrowser->lpvtbl->fnGetWindow(this->pShellBrowser, &(this->hWndParent));
*phWnd = CreateWindowEx32A(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
prcView->left, prcView->top, prcView->right - prcView->left, prcView->bottom - prcView->top,
this->hWndParent, 0, shell32_hInstance, (LPVOID)this);
if(!*phWnd)
return E_FAIL;
this->pShellBrowser->lpvtbl->fnAddRef(this->pShellBrowser);
return S_OK;
}
static HRESULT WINAPI IShellView_DestroyViewWindow(LPSHELLVIEW this)
{ FIXME(shell,"(%p) stub\n",this);
this->pShellBrowser->lpvtbl->fnRelease(this->pShellBrowser);
return S_OK;
}
static HRESULT WINAPI IShellView_GetCurrentInfo(LPSHELLVIEW this, LPFOLDERSETTINGS lpfs)
{ FIXME(shell,"(%p)->(%p)stub\n",this, lpfs);
*lpfs = this->FolderSettings;
return S_OK;
}
static HRESULT WINAPI IShellView_AddPropertySheetPages(LPSHELLVIEW this, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
{ FIXME(shell,"(%p) stub\n",this);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellView_SaveViewState(LPSHELLVIEW this)
{ FIXME(shell,"(%p) stub\n",this);
return S_OK;
}
static HRESULT WINAPI IShellView_SelectItem(LPSHELLVIEW this, LPCITEMIDLIST pidlItem, UINT32 uFlags)
{ FIXME(shell,"(%p)->(pidl=%p, 0x%08x) stub\n",this, pidlItem, uFlags);
return E_NOTIMPL;
}
static HRESULT WINAPI IShellView_GetItemObject(LPSHELLVIEW this, UINT32 uItem, REFIID riid,LPVOID *ppvOut)
{ char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
FIXME(shell,"(%p)->(0x%08x,\n\t%s, %p)stub\n",this, uItem, xriid, ppvOut);
*ppvOut = NULL;
return E_NOTIMPL;
}
/***********************************************************************
* IShellFolder implementation
*/
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_ParseDisplayName,
IShellFolder_EnumObjects,
IShellFolder_BindToObject,
IShellFolder_BindToStorage,
IShellFolder_CompareIDs,
IShellFolder_CreateViewObject,
IShellFolder_GetAttributesOf,
IShellFolder_GetUIObjectOf,
IShellFolder_GetDisplayNameOf,
IShellFolder_SetNameOf
/* IShellFolder_Initialize*/
};
/**************************************************************************
* IShellFolder_Constructor
*/
LPSHELLFOLDER IShellFolder_Constructor(LPSHELLFOLDER pParent,LPITEMIDLIST pidl)
{ LPSHELLFOLDER sf;
DWORD dwSize=0;
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);
/* create own pidl-manager*/
sf->pPidlMgr = PidlMgr_Constructor();
if (! sf->pPidlMgr )
{ HeapFree(GetProcessHeap(),0,sf);
ERR (shell,"-- Could not initialize PidMGR\n");
return NULL;
}
/* keep a copy of the pidl in the instance*/
sf->mpidl = ILClone(pidl);
sf->mpidlNSRoot = NULL;
if(sf->mpidl) /* do we have a pidl?*/
{ 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 = SHAlloc(dwSize);
if(sf->mlpszFolder)
{ *(sf->mlpszFolder)=0x00;
if(sf->mpSFParent->mlpszFolder)
{ strcpy(sf->mlpszFolder, sf->mpSFParent->mlpszFolder);
PathAddBackslash (sf->mlpszFolder);
}
sf->pPidlMgr->lpvtbl->fnGetFolderText(sf->pPidlMgr, sf->mpidl, sf->mlpszFolder+strlen(sf->mlpszFolder), dwSize-strlen(sf->mlpszFolder));
}
}
TRACE(shell,"-- (%p)->(%p,%p,parent=%s)\n",sf,pParent, pidl, debugstr_a(sf->mlpszFolder));
return sf;
}
/**************************************************************************
* IShellFolder::QueryInterface
* PARAMETERS
* REFIID riid, //[in ] Requested InterfaceID
* LPVOID* ppvObject) //[out] Interface* to hold the result
*/
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);
if (pdesktopfolder==this)
{ pdesktopfolder=NULL;
TRACE(shell,"-- destroyed IShellFolder(%p) was Desktopfolder\n",this);
}
if (this->pPidlMgr)
{ PidlMgr_Destructor(this->pPidlMgr);
}
if(this->mpidlNSRoot)
{ SHFree(this->mpidlNSRoot);
}
if(this->mpidl)
{ SHFree(this->mpidl);
}
if(this->mlpszFolder)
{ SHFree(this->mlpszFolder);
}
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
/**************************************************************************
* IShellFolder_ParseDisplayName
* 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
*
* FIXME:
* pdwAttributes: not used
*/
static HRESULT WINAPI IShellFolder_ParseDisplayName(
LPSHELLFOLDER this,
HWND32 hwndOwner,
LPBC pbcReserved,
LPOLESTR32 lpszDisplayName,
DWORD *pchEaten,
LPITEMIDLIST *ppidl,
DWORD *pdwAttributes)
{ HRESULT hr=E_OUTOFMEMORY;
LPITEMIDLIST pidlFull=NULL, pidlTemp = NULL, pidlOld = NULL;
LPSTR pszNext=NULL;
CHAR szElement[MAX_PATH];
BOOL32 bType;
DWORD dwChars=lstrlen32W(lpszDisplayName) + 1;
LPSTR pszTemp=(LPSTR)HeapAlloc(GetProcessHeap(),0,dwChars * sizeof(CHAR));
TRACE(shell,"(%p)->(HWND=0x%08x,%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)
{ if (strcmp(pszTemp,"Desktop")==0)
{ pidlFull = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,2);
pidlFull->mkid.cb = 0;
}
else
{ pidlFull = this->pPidlMgr->lpvtbl->fnCreateMyComputer(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 = ILCombine(pidlFull,pidlTemp);
SHFree(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 = ILCombine(pidlFull,pidlTemp);
SHFree(pidlOld);
}
hr = S_OK;
}
}
}
}
HeapFree(GetProcessHeap(),0,pszTemp);
*ppidl = pidlFull;
return hr;
}
/**************************************************************************
* IShellFolder_EnumObjects
* PARAMETERS
* HWND hwndOwner, //[in ] Parent Window
* DWORD grfFlags, //[in ] SHCONTF enumeration mask
* LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
*/
static HRESULT WINAPI IShellFolder_EnumObjects(
LPSHELLFOLDER this,
HWND32 hwndOwner,
DWORD dwFlags,
LPENUMIDLIST* ppEnumIDList)
{ HRESULT hr;
TRACE(shell,"(%p)->(HWND=0x%08x,0x%08lx,%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)
{ SHFree(this->mpidlNSRoot);
this->mpidlNSRoot = NULL;
}
this->mpidlNSRoot=ILClone(pidl);
return S_OK;
}
/**************************************************************************
* IShellFolder_BindToObject
* PARAMETERS
* LPCITEMIDLIST pidl, //[in ] complex pidl to open
* LPBC pbc, //[in ] reserved
* REFIID riid, //[in ] Initial Interface
* LPVOID* ppvObject //[out] Interface*
*/
static HRESULT WINAPI IShellFolder_BindToObject(
LPSHELLFOLDER this,
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
LPVOID * ppvOut)
{ char xriid[50];
HRESULT hr;
LPSHELLFOLDER pShellFolder;
WINE_StringFromCLSID(riid,xriid);
TRACE(shell,"(%p)->(pidl=%p,%p,\n\tIID:%s,%p)\n",this,pidl,pbcReserved,xriid,ppvOut);
*ppvOut = NULL;
pShellFolder = IShellFolder_Constructor(this, pidl);
if(!pShellFolder)
return E_OUTOFMEMORY;
/* pShellFolder->lpvtbl->fnInitialize(pShellFolder, this->mpidlNSRoot);*/
IShellFolder_Initialize(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
* 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_BindToStorage(
LPSHELLFOLDER this,
LPCITEMIDLIST pidl, /*simple/complex pidl*/
LPBC pbcReserved,
REFIID riid,
LPVOID *ppvOut)
{ char xriid[50];
WINE_StringFromCLSID(riid,xriid);
FIXME(shell,"(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",this,pidl,pbcReserved,xriid,ppvOut);
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* IShellFolder_CompareIDs
*
* PARMETERS
* LPARAM lParam, //[in ] Column?
* LPCITEMIDLIST pidl1, //[in ] simple pidl
* LPCITEMIDLIST pidl2) //[in ] simple pidl
* FIXME
* we have to handle simple pidl's only
*/
static HRESULT WINAPI IShellFolder_CompareIDs(
LPSHELLFOLDER this,
LPARAM lParam,
LPCITEMIDLIST pidl1, /*simple pidl*/
LPCITEMIDLIST pidl2) /*simple pidl*/
{ CHAR szString1[MAX_PATH] = "";
CHAR szString2[MAX_PATH] = "";
int nReturn;
LPCITEMIDLIST pidlTemp1 = pidl1, pidlTemp2 = pidl2;
TRACE(shell,"(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\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
* Creates an View Object representing the ShellFolder
* IShellView / IShellBrowser / IContextMenu
*
* PARAMETERS
* HWND hwndOwner, // Handle of owner window
* REFIID riid, // Requested initial interface
* LPVOID* ppvObject) // Resultant interface*
*
* NOTES
* the same as SHCreateShellFolderViewEx ???
*/
static HRESULT WINAPI IShellFolder_CreateViewObject(
LPSHELLFOLDER this,
HWND32 hwndOwner,
REFIID riid,
LPVOID *ppvOut)
{ LPSHELLVIEW pShellView;
char xriid[50];
HRESULT hr;
WINE_StringFromCLSID(riid,xriid);
TRACE(shell,"(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",this,hwndOwner,xriid,ppvOut);
*ppvOut = NULL;
pShellView = IShellView_Constructor(this, this->mpidl);
if(!pShellView)
return E_OUTOFMEMORY;
hr = pShellView->lpvtbl->fnQueryInterface(pShellView, riid, ppvOut);
pShellView->lpvtbl->fnRelease(pShellView);
TRACE(shell,"-- (%p)->(interface=%p)\n",this, ppvOut);
return hr;
}
/**************************************************************************
* IShellFolder_GetAttributesOf
*
* PARAMETERS
* UINT cidl, //[in ] num elements in pidl array
+ LPCITEMIDLIST* apidl, //[in ] simple pidl array
* ULONG* rgfInOut) //[out] result array
*
* FIXME: quick hack
* Note: rgfInOut is documented as being an array of ULONGS.
* This does not seem to be the case. Testing this function using the shell to
* call it with cidl > 1 (by deleting multiple items) reveals that the shell
* passes ONE element in the array and writing to further elements will
* cause the shell to fail later.
*/
static HRESULT WINAPI IShellFolder_GetAttributesOf(
LPSHELLFOLDER this,
UINT32 cidl,
LPCITEMIDLIST *apidl, /*simple pidl's*/
DWORD *rgfInOut)
{ LPCITEMIDLIST * pidltemp;
DWORD i;
TRACE(shell,"(%p)->(%d,%p,%p)\n",this,cidl,apidl,rgfInOut);
pidltemp=apidl;
*rgfInOut = 0x00;
i=cidl;
if ((! cidl )| (!apidl) | (!rgfInOut))
return E_INVALIDARG;
do
{ if (*pidltemp)
{ if (this->pPidlMgr->lpvtbl->fnIsDesktop(this->pPidlMgr, *pidltemp))
{ *rgfInOut |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR);
}
else if (this->pPidlMgr->lpvtbl->fnIsMyComputer(this->pPidlMgr, *pidltemp))
{ *rgfInOut |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
}
else if (this->pPidlMgr->lpvtbl->fnIsDrive(this->pPidlMgr, *pidltemp))
{ *rgfInOut |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM);
}
else if (this->pPidlMgr->lpvtbl->fnIsFolder(this->pPidlMgr, *pidltemp))
{ *rgfInOut |= (SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER);
}
else if (this->pPidlMgr->lpvtbl->fnIsValue(this->pPidlMgr, *pidltemp))
{ *rgfInOut |= (SFGAO_FILESYSTEM);
}
}
pidltemp++;
cidl--;
} while (cidl > 0 && *pidltemp);
return S_OK;
}
/**************************************************************************
* IShellFolder_GetUIObjectOf
*
* 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_GetUIObjectOf(
LPSHELLFOLDER this,
HWND32 hwndOwner,
UINT32 cidl,
LPCITEMIDLIST * apidl, /* simple pidl's*/
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);
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* IShellFolder_GetDisplayNameOf
* 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_GetDisplayNameOf(
LPSHELLFOLDER this,
LPCITEMIDLIST pidl, /* simple/complex pidl*/
DWORD dwFlags,
LPSTRRET lpName)
{ CHAR szText[MAX_PATH];
CHAR szTemp[MAX_PATH];
CHAR szSpecial[MAX_PATH];
CHAR szDrive[MAX_PATH];
DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
LPITEMIDLIST pidlTemp=NULL;
BOOL32 bSimplePidl=FALSE;
TRACE(shell,"(%p)->(pidl=%p,0x%08lx,%p)\n",this,pidl,dwFlags,lpName);
if (!pidl)
{ return E_OUTOFMEMORY;
}
szSpecial[0]=0x00;
szDrive[0]=0x00;
/* test if simple(relative) or complex(absolute) pidl */
pidlTemp = this->pPidlMgr->lpvtbl->fnGetNextItem(this->pPidlMgr,pidl);
if (pidlTemp->mkid.cb==0x00)
{ bSimplePidl = TRUE;
}
if (this->pPidlMgr->lpvtbl->fnIsDesktop(this->pPidlMgr, pidl))
{ strcpy (szText,"Desktop");
}
else
{ if (this->pPidlMgr->lpvtbl->fnIsMyComputer(this->pPidlMgr, pidl))
{ this->pPidlMgr->lpvtbl->fnGetItemText(this->pPidlMgr, pidl, szSpecial, MAX_PATH);
}
if (this->pPidlMgr->lpvtbl->fnIsDrive(this->pPidlMgr, pidl))
{ pidlTemp = this->pPidlMgr->lpvtbl->fnGetLastItem(this->pPidlMgr,pidl);
if (pidlTemp)
{ this->pPidlMgr->lpvtbl->fnGetItemText(this->pPidlMgr, pidlTemp, szTemp, MAX_PATH);
}
if ( dwFlags==SHGDN_NORMAL || dwFlags==SHGDN_INFOLDER)
{ GetVolumeInformation32A(szTemp,szDrive,MAX_PATH,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
if (szTemp[2]=='\\')
{ szTemp[2]=0x00;
}
strcat (szDrive," (");
strcat (szDrive,szTemp);
strcat (szDrive,")");
}
else
{ PathAddBackslash (szTemp);
strcpy(szDrive,szTemp);
}
}
switch(dwFlags)
{ case SHGDN_NORMAL:
this->pPidlMgr->lpvtbl->fnGetPidlPath(this->pPidlMgr, pidl, szText, MAX_PATH);
break;
case SHGDN_INFOLDER:
pidlTemp = this->pPidlMgr->lpvtbl->fnGetLastItem(this->pPidlMgr,pidl);
if (pidlTemp)
{ this->pPidlMgr->lpvtbl->fnGetItemText(this->pPidlMgr, pidlTemp, szText, MAX_PATH);
}
break;
case SHGDN_FORPARSING:
if (bSimplePidl)
{ /* if the IShellFolder has parents, get the path from the
parent and add the ItemName*/
szText[0]=0x00;
if (this->mlpszFolder && strlen (this->mlpszFolder))
{ if (strcmp(this->mlpszFolder,"My Computer"))
{ strcpy (szText,this->mlpszFolder);
PathAddBackslash (szText);
}
}
pidlTemp = this->pPidlMgr->lpvtbl->fnGetLastItem(this->pPidlMgr,pidl);
if (pidlTemp)
{ this->pPidlMgr->lpvtbl->fnGetItemText(this->pPidlMgr, pidlTemp, szTemp, MAX_PATH );
}
strcat(szText,szTemp);
}
else
{ /* if the pidl is absolute, get everything from the pidl*/
this->pPidlMgr->lpvtbl->fnGetPidlPath(this->pPidlMgr, pidl, szText, MAX_PATH);
}
break;
default: return E_INVALIDARG;
}
if ((szText[0]==0x00 && szDrive[0]!=0x00)|| (bSimplePidl && szDrive[0]!=0x00))
{ strcpy(szText,szDrive);
}
if (szText[0]==0x00 && szSpecial[0]!=0x00)
{ strcpy(szText,szSpecial);
}
}
TRACE(shell,"-- (%p)->(%s,%s,%s)\n",this,szSpecial,szDrive,szText);
if(!(lpName))
{ return E_OUTOFMEMORY;
}
lpName->uType = STRRET_CSTR;
strcpy(lpName->u.cStr,szText);
return S_OK;
}
/**************************************************************************
* IShellFolder_SetNameOf
* 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_SetNameOf(
LPSHELLFOLDER this,
HWND32 hwndOwner,
LPCITEMIDLIST pidl, /*simple 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 Implementation
*/
static HRESULT WINAPI IShellLink_QueryInterface(LPSHELLLINK,REFIID,LPVOID*);
static ULONG WINAPI IShellLink_AddRef(LPSHELLLINK);
static ULONG WINAPI IShellLink_Release(LPSHELLLINK);
/**************************************************************************
* IShellLink_VTable
*/
static struct IShellLink_VTable slvt = {
IShellLink_QueryInterface,
IShellLink_AddRef,
IShellLink_Release,
(void *)0xcafe0004,
(void *)0xcafe0005,
(void *)0xcafe0006,
(void *)0xcafe0007,
(void *)0xcafe0008,
(void *)0xcafe0009,
(void *)0xcafe0010,
(void *)0xcafe0011,
(void *)0xcafe0012,
(void *)0xcafe0013,
(void *)0xcafe0014,
(void *)0xcafe0015,
(void *)0xcafe0016,
(void *)0xcafe0017,
(void *)0xcafe0018,
(void *)0xcafe0019,
(void *)0xcafe0020,
(void *)0xcafe0021
};
/**************************************************************************
* 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;
}
/**************************************************************************
* IShellLink::QueryInterface
*/
static HRESULT WINAPI IShellLink_QueryInterface(
LPSHELLLINK 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_IShellLink)) /*IShellLink*/
{ *ppvObj = (LPSHELLLINK)this;
}
if(*ppvObj)
{ (*(LPSHELLLINK*)ppvObj)->lpvtbl->fnAddRef(this);
TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE(shell,"-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/******************************************************************************
* IShellLink_AddRef
*/
static ULONG WINAPI IShellLink_AddRef(LPSHELLLINK this)
{ TRACE(shell,"(%p)->(count=%lu)\n",this,this->ref);
return ++(this->ref);
}
/******************************************************************************
* IClassFactory_Release
*/
static ULONG WINAPI IShellLink_Release(LPSHELLLINK this)
{ TRACE(shell,"(%p)->(count=%lu)\n",this,this->ref);
if (!--(this->ref))
{ TRACE(shell,"-- destroying IShellLink(%p)\n",this);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
/**************************************************************************
* INTERNAL CLASS pidlmgr
*/
LPITEMIDLIST PidlMgr_CreateDesktop(LPPIDLMGR);
LPITEMIDLIST PidlMgr_CreateMyComputer(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);
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_IsMyComputer(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_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_CreateMyComputer,
PidlMgr_CreateDrive,
PidlMgr_CreateFolder,
PidlMgr_CreateValue,
/* PidlMgr_Delete,*/
PidlMgr_GetNextItem,
PidlMgr_GetDesktop,
PidlMgr_GetDrive,
PidlMgr_GetLastItem,
PidlMgr_GetItemText,
PidlMgr_IsDesktop,
PidlMgr_IsMyComputer,
PidlMgr_IsDrive,
PidlMgr_IsFolder,
PidlMgr_IsValue,
PidlMgr_HasFolders,
PidlMgr_GetFolderText,
PidlMgr_GetValueText,
PidlMgr_GetValueType,
PidlMgr_GetDataText,
PidlMgr_GetPidlPath,
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_CreateMyComputer()
* PidlMgr_CreateDrive()
* PidlMgr_CreateFolder()
* PidlMgr_CreateValue()
*/
LPITEMIDLIST PidlMgr_CreateDesktop(LPPIDLMGR this)
{ TRACE(shell,"(%p)->()\n",this);
return PidlMgr_Create(this,PT_DESKTOP, NULL, 0);
}
LPITEMIDLIST PidlMgr_CreateMyComputer(LPPIDLMGR this)
{ TRACE(shell,"(%p)->()\n",this);
return PidlMgr_Create(this,PT_MYCOMP, (void *)"My Computer", strlen ("My Computer")+1);
}
LPITEMIDLIST PidlMgr_CreateDrive(LPPIDLMGR this, LPCSTR lpszNew)
{ char sTemp[4];
strncpy (sTemp,lpszNew,4);
sTemp[2]='\\';
sTemp[3]=0x00;
TRACE(shell,"(%p)->(%s)\n",this,sTemp);
return PidlMgr_Create(this,PT_DRIVE,(LPVOID)&sTemp[0],4);
}
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)
{ LPITEMIDLIST nextpidl;
TRACE(shell,"(%p)->(pidl=%p)\n",this,pidl);
if(pidl)
{ nextpidl = (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
/* TRACE(shell,"-- (%p)->(next pidl=%p)\n",this,nextpidl);*/
return nextpidl;
}
else
{ return (NULL);
}
}
/**************************************************************************
* 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_IsMyComputer(this,pidl))
{ pidlTemp = PidlMgr_GetNextItem(this,pidl);
}
else if (pidlTemp && PidlMgr_IsDrive(this,pidlTemp))
{ 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_IsMyComputer(this, pidl))
{ return PidlMgr_GetData(this,PT_MYCOMP, 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)
{ TRACE(shell,"%p->(%p)\n",this,pidl);
if (! pidl)
return FALSE;
return ( pidl->mkid.cb == 0x00 );
}
BOOL32 PidlMgr_IsMyComputer(LPPIDLMGR this,LPCITEMIDLIST pidl)
{ LPPIDLDATA pData;
TRACE(shell,"%p->(%p)\n",this,pidl);
if (! pidl)
return FALSE;
pData = PidlMgr_GetDataPointer(this,pidl);
return (PT_MYCOMP == pData->type);
}
BOOL32 PidlMgr_IsDrive(LPPIDLMGR this,LPCITEMIDLIST pidl)
{ LPPIDLDATA pData;
TRACE(shell,"%p->(%p)\n",this,pidl);
if (! pidl)
return FALSE;
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);
if (! pidl)
return FALSE;
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);
if (! pidl)
return FALSE;
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 special Folders
*/
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_IsMyComputer(this,pidl))
{ pidlTemp = PidlMgr_GetNextItem(this,pidl);
TRACE(shell,"-- (%p)->skip My Computer\n",this);
}
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
TRACE(shell,"-- (%p)->(size=%lu)\n",this,dwCopied);
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);
TRACE(shell,"-- (%p)->(size=%lu,%s)\n",this,dwCopied,lpszPath);
}
//remove the last backslash if necessary
if(dwCopied)
{ if(*(lpszPath + strlen(lpszPath) - 1) == '\\')
{ *(lpszPath + strlen(lpszPath) - 1) = 0;
dwCopied--;
}
}
TRACE(shell,"-- (%p)->(path=%s)\n",this,lpszPath);
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 0x%08lx)\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 0x%08lx)\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 || !pidlPath || !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 0x%08lx)\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_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 ( type == PT_DESKTOP)
{ pidlOut = SHAlloc(2);
pidlOut->mkid.cb=0x0000;
return pidlOut;
}
if (! pIn)
{ return NULL;
}
uSize = 2 + (sizeof(PIDLTYPE)) + uInSize + 2; /* cb + PIDLTYPE + uInSize +2 */
pidlOut = SHAlloc(uSize);
pidlTemp = pidlOut;
if(pidlOut)
{ pidlTemp->mkid.cb = uSize - 2;
pData =(LPPIDLDATA) &(pidlTemp->mkid.abID[0]);
pData->type = type;
switch(type)
{ case PT_MYCOMP:
memcpy(pData->szText, pIn, uInSize);
TRACE(shell,"- (%p)->create My Computer: %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 = 0x00;
}
TRACE(shell,"-- (%p)->(pidl=%p, size=%u)\n",this,pidlOut,uSize-2);
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_MYCOMP: if(uOutSize < 1)
return 0;
if(PT_MYCOMP != pData->type)
return 0;
*(LPSTR)pOut = 0;
strncpy((LPSTR)pOut, "My Computer", uOutSize);
dwReturn = strlen((LPSTR)pOut);
break;
case PT_DRIVE: if(uOutSize < 1)
return 0;
if(PT_DRIVE != pData->type)
return 0;
*(LPSTR)pOut = 0;
strncpy((LPSTR)pOut, pData->szText, 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;
default: break;
}
TRACE(shell,"-- (%p)->(%p=%s 0x%08lx)\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 = ILClone(*ppidlValue);
*ppidlPath = ILClone(pidlFQ);
pidlTemp = PidlMgr_GetLastItem(this,*ppidlPath);
pidlTemp->mkid.cb = 0x00;
return TRUE;
}