diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in index 648c070a5fa..aef7eddcd13 100644 --- a/dlls/shell32/Makefile.in +++ b/dlls/shell32/Makefile.in @@ -18,6 +18,7 @@ C_SRCS = \ classes.c \ clipboard.c \ control.c \ + cpanelfolder.c \ dataobject.c \ debughlp.c \ dialogs.c \ diff --git a/dlls/shell32/control.c b/dlls/shell32/control.c index 40a2c809c96..095f65e7ad2 100644 --- a/dlls/shell32/control.c +++ b/dlls/shell32/control.c @@ -36,27 +36,11 @@ #define NO_SHLWAPI_REG #include "shlwapi.h" +#include "cpanel.h" + WINE_DEFAULT_DEBUG_CHANNEL(shlctrl); -typedef struct CPlApplet { - struct CPlApplet* next; /* linked list */ - HWND hWnd; - unsigned count; /* number of subprograms */ - HMODULE hModule; /* module of loaded applet */ - APPLET_PROC proc; /* entry point address */ - NEWCPLINFOW info[1]; /* array of count information. - * dwSize field is 0 if entry is invalid */ -} CPlApplet; - -typedef struct CPanel { - CPlApplet* first; /* linked list */ - HWND hWnd; - unsigned status; - CPlApplet* clkApplet; - unsigned clkSP; -} CPanel; - -static CPlApplet* Control_UnloadApplet(CPlApplet* applet) +CPlApplet* Control_UnloadApplet(CPlApplet* applet) { unsigned i; CPlApplet* next; @@ -72,7 +56,7 @@ static CPlApplet* Control_UnloadApplet(CPlApplet* applet) return next; } -static CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) +CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) { CPlApplet* applet; unsigned i; diff --git a/dlls/shell32/cpanel.h b/dlls/shell32/cpanel.h new file mode 100644 index 00000000000..1d37d985191 --- /dev/null +++ b/dlls/shell32/cpanel.h @@ -0,0 +1,45 @@ +/* Control Panel management + * + * Copyright 2001 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SHELL_CPANEL_H +#define __WINE_SHELL_CPANEL_H + +typedef struct CPlApplet { + struct CPlApplet* next; /* linked list */ + HWND hWnd; + unsigned count; /* number of subprograms */ + HMODULE hModule; /* module of loaded applet */ + APPLET_PROC proc; /* entry point address */ + NEWCPLINFOW info[1]; /* array of count information. + * dwSize field is 0 if entry is invalid */ +} CPlApplet; + +typedef struct CPanel { + CPlApplet* first; /* linked list */ + HWND hWnd; + unsigned status; + CPlApplet* clkApplet; + unsigned clkSP; +} CPanel; + + +CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel); +CPlApplet* Control_UnloadApplet(CPlApplet* applet); + +#endif /* __WINE_SHELL_CPANEL_H */ diff --git a/dlls/shell32/cpanelfolder.c b/dlls/shell32/cpanelfolder.c new file mode 100644 index 00000000000..0bf054b3101 --- /dev/null +++ b/dlls/shell32/cpanelfolder.c @@ -0,0 +1,875 @@ +/* + * Control panel folder + * + * Copyright 2003 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or(at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "ole2.h" +#include "shlguid.h" + +#include "pidl.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shresdef.h" +#include "shlwapi.h" +#include "shellfolder.h" +#include "wine/debug.h" +#include "debughlp.h" +#include "shfldr.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/*********************************************************************** +* control panel implementation in shell namespace +*/ + +typedef struct { + ICOM_VFIELD(IShellFolder2); + DWORD ref; + + ICOM_VTABLE(IPersistFolder2)* lpVtblPersistFolder2; + ICOM_VTABLE(IShellExecuteHookW)* lpVtblShellExecuteHookW; + ICOM_VTABLE(IShellExecuteHookA)* lpVtblShellExecuteHookA; + + IUnknown *pUnkOuter; /* used for aggregation */ + + /* both paths are parsible from the desktop */ + LPITEMIDLIST pidlRoot; /* absolute pidl */ + int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ +} ICPanelImpl; + +static ICOM_VTABLE(IShellFolder2) vt_ShellFolder2; +static ICOM_VTABLE(IPersistFolder2) vt_PersistFolder2; +static ICOM_VTABLE(IShellExecuteHookW) vt_ShellExecuteHookW; +static ICOM_VTABLE(IShellExecuteHookA) vt_ShellExecuteHookA; + +#define _IPersistFolder2_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblPersistFolder2))) +#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset); + +#define IShellExecuteHookW_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblShellExecuteHookW))) +#define _ICOM_THIS_From_IShellExecuteHookW(class, name) class* This = (class*)(((char*)name)-IShellExecuteHookW_Offset); + +#define IShellExecuteHookA_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblShellExecuteHookA))) +#define _ICOM_THIS_From_IShellExecuteHookA(class, name) class* This = (class*)(((char*)name)-IShellExecuteHookA_Offset); + + +/* + converts This to a interface pointer +*/ +#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) +#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) +#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpVtbl) + +#define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2) +#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2) +#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2) +#define _IShellExecuteHookW_(This) (IShellExecuteHookW*)&(This->lpVtblShellExecuteHookW) +#define _IShellExecuteHookA_(This) (IShellExecuteHookA*)&(This->lpVtblShellExecuteHookA) + +/*********************************************************************** +* IShellFolder [ControlPanel] implementation +*/ + +static shvheader ControlPanelSFHeader[] = { + {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},/*FIXME*/ + {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 200},/*FIXME*/ +}; + +#define CONROLPANELSHELLVIEWCOLUMNS 2 + +/************************************************************************** +* IControlPanel_Constructor +*/ +HRESULT WINAPI IControlPanel_Constructor(IUnknown* pUnkOuter, REFIID riid, LPVOID * ppv) +{ + ICPanelImpl *sf; + + TRACE("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid(riid)); + + if (!ppv) + return E_POINTER; + if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) + return CLASS_E_NOAGGREGATION; + + sf = (ICPanelImpl *) LocalAlloc(GMEM_ZEROINIT, sizeof(ICPanelImpl)); + if (!sf) + return E_OUTOFMEMORY; + + sf->ref = 0; + sf->lpVtbl = &vt_ShellFolder2; + sf->lpVtblPersistFolder2 = &vt_PersistFolder2; + sf->lpVtblShellExecuteHookW = &vt_ShellExecuteHookW; + sf->lpVtblShellExecuteHookA = &vt_ShellExecuteHookA; + sf->pidlRoot = _ILCreateControl(); /* my qualified pidl */ + sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf); + + if (!SUCCEEDED(IUnknown_QueryInterface(_IUnknown_(sf), riid, ppv))) { + IUnknown_Release(_IUnknown_(sf)); + return E_NOINTERFACE; + } + + TRACE("--(%p)\n", sf); + return S_OK; +} + +/************************************************************************** + * ISF_ControlPanel_fnQueryInterface + * + * NOTES supports not IPersist/IPersistFolder + */ +static HRESULT WINAPI ISF_ControlPanel_fnQueryInterface(IShellFolder2 * iface, REFIID riid, LPVOID * ppvObject) +{ + ICOM_THIS(ICPanelImpl, iface); + + TRACE("(%p)->(%s,%p)\n", This, shdebugstr_guid(riid), ppvObject); + + *ppvObject = NULL; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IShellFolder) || IsEqualIID(riid, &IID_IShellFolder2)) + *ppvObject = This; + else if (IsEqualIID(riid, &IID_IPersist) || + IsEqualIID(riid, &IID_IPersistFolder) || IsEqualIID(riid, &IID_IPersistFolder2)) + *ppvObject = _IPersistFolder2_(This); + else if (IsEqualIID(riid, &IID_IShellExecuteHookW)) + *ppvObject = _IShellExecuteHookW_(This); + else if (IsEqualIID(riid, &IID_IShellExecuteHookA)) + *ppvObject = _IShellExecuteHookA_(This); + + if (*ppvObject) { + IUnknown_AddRef((IUnknown *)(*ppvObject)); + TRACE("-- Interface:(%p)->(%p)\n", ppvObject, *ppvObject); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ISF_ControlPanel_fnAddRef(IShellFolder2 * iface) +{ + ICOM_THIS(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return ++(This->ref); +} + +static ULONG WINAPI ISF_ControlPanel_fnRelease(IShellFolder2 * iface) +{ + ICOM_THIS(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + if (!--(This->ref)) { + TRACE("-- destroying IShellFolder(%p)\n", This); + if (This->pidlRoot) + SHFree(This->pidlRoot); + LocalFree((HLOCAL) This); + return 0; + } + return This->ref; +} + +/************************************************************************** +* ISF_ControlPanel_fnParseDisplayName +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnParseDisplayName(IShellFolder2 * iface, + HWND hwndOwner, + LPBC pbc, + LPOLESTR lpszDisplayName, + DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) +{ + ICOM_THIS(ICPanelImpl, iface); + + HRESULT hr = E_INVALIDARG; + + FIXME("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", + This, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName), pchEaten, ppidl, pdwAttributes); + + *ppidl = 0; + if (pchEaten) + *pchEaten = 0; + + TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr); + + return hr; +} + +/************************************************************************** +* ISF_ControlPanel_fnEnumObjects +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnEnumObjects(IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) +{ + ICOM_THIS(ICPanelImpl, iface); + + TRACE("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); + + *ppEnumIDList = IEnumIDList_Constructor(NULL, dwFlags, EIDL_CPANEL); + + TRACE("--(%p)->(new ID List: %p)\n", This, *ppEnumIDList); + + return(*ppEnumIDList) ? S_OK : E_OUTOFMEMORY; +} + +/************************************************************************** +* ISF_ControlPanel_fnBindToObject +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnBindToObject(IShellFolder2 * iface, LPCITEMIDLIST pidl, + LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + ICOM_THIS(ICPanelImpl, iface); + + TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid(riid), ppvOut); + + return SHELL32_BindToChild(This->pidlRoot, NULL, pidl, riid, ppvOut); +} + +/************************************************************************** +* ISF_ControlPanel_fnBindToStorage +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnBindToStorage(IShellFolder2 * iface, + LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + ICOM_THIS(ICPanelImpl, iface); + + FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid(riid), ppvOut); + + *ppvOut = NULL; + return E_NOTIMPL; +} + +/************************************************************************** +* ISF_ControlPanel_fnCompareIDs +*/ + +static HRESULT WINAPI +ISF_ControlPanel_fnCompareIDs(IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + ICOM_THIS(ICPanelImpl, iface); + + int nReturn; + + TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); + nReturn = SHELL32_CompareIDs(_IShellFolder_(This), lParam, pidl1, pidl2); + TRACE("-- %i\n", nReturn); + return nReturn; +} + +/************************************************************************** +* ISF_ControlPanel_fnCreateViewObject +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnCreateViewObject(IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut) +{ + ICOM_THIS(ICPanelImpl, iface); + + LPSHELLVIEW pShellView; + HRESULT hr = E_INVALIDARG; + + TRACE("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid(riid), ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID(riid, &IID_IDropTarget)) { + WARN("IDropTarget not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID(riid, &IID_IContextMenu)) { + WARN("IContextMenu not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID(riid, &IID_IShellView)) { + pShellView = IShellView_Constructor((IShellFolder *) iface); + if (pShellView) { + hr = IShellView_QueryInterface(pShellView, riid, ppvOut); + IShellView_Release(pShellView); + } + } + } + TRACE("--(%p)->(interface=%p)\n", This, ppvOut); + return hr; +} + +/************************************************************************** +* ISF_ControlPanel_fnGetAttributesOf +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnGetAttributesOf(IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) +{ + ICOM_THIS(ICPanelImpl, iface); + + HRESULT hr = S_OK; + + TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); + + if ((!cidl) ||(!apidl) ||(!rgfInOut)) + return E_INVALIDARG; + + while(cidl > 0 && *apidl) { + pdump(*apidl); + SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut); + apidl++; + cidl--; + } + + TRACE("-- result=0x%08lx\n", *rgfInOut); + return hr; +} + +/************************************************************************** +* ISF_ControlPanel_fnGetUIObjectOf +* +* PARAMETERS +* HWND hwndOwner, //[in ] Parent window for any output +* UINT cidl, //[in ] array size +* LPCITEMIDLIST* apidl, //[in ] simple pidl array +* REFIID riid, //[in ] Requested Interface +* UINT* prgfInOut, //[ ] reserved +* LPVOID* ppvObject) //[out] Resulting Interface +* +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnGetUIObjectOf(IShellFolder2 * iface, + HWND hwndOwner, + UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) +{ + ICOM_THIS(ICPanelImpl, iface); + + LPITEMIDLIST pidl; + IUnknown *pObj = NULL; + HRESULT hr = E_INVALIDARG; + + TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", + This, hwndOwner, cidl, apidl, shdebugstr_guid(riid), prgfInOut, ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID(riid, &IID_IContextMenu) &&(cidl >= 1)) { + pObj = (LPUNKNOWN) ISvItemCm_Constructor((IShellFolder *) iface, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1)) { + pObj = (LPUNKNOWN) IDataObject_Constructor(hwndOwner, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID(riid, &IID_IExtractIconA) &&(cidl == 1)) { + pidl = ILCombine(This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconA_Constructor(pidl); + SHFree(pidl); + hr = S_OK; + } else if (IsEqualIID(riid, &IID_IExtractIconW) &&(cidl == 1)) { + pidl = ILCombine(This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconW_Constructor(pidl); + SHFree(pidl); + hr = S_OK; + } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) + && (cidl == 1)) { + pidl = ILCombine(This->pidlRoot, apidl[0]); + hr = IShellLink_ConstructFromFile(NULL, riid, pidl,(LPVOID*)&pObj); + SHFree(pidl); + } else { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr) && !pObj) + hr = E_OUTOFMEMORY; + + *ppvOut = pObj; + } + TRACE("(%p)->hr=0x%08lx\n", This, hr); + return hr; +} + +/************************************************************************** +* ISF_ControlPanel_fnGetDisplayNameOf +*/ +static HRESULT WINAPI ISF_ControlPanel_fnGetDisplayNameOf(IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) +{ + ICOM_THIS(ICPanelImpl, iface); + + CHAR szPath[MAX_PATH*2]; + PIDLCPanelStruct* pcpanel; + + *szPath = '\0'; + + TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); + pdump(pidl); + + if (!pidl || !strRet) + return E_INVALIDARG; + + pcpanel = _ILGetCPanelPointer(pidl); + + if (pcpanel) { + lstrcpyA(szPath, pcpanel->szName+pcpanel->offsDispName); + + if (!(dwFlags & SHGDN_FORPARSING)) + FIXME("retrieve display name from control panel app\n"); + } + /* take names of special folders only if its only this folder */ + else if (_ILIsSpecialFolder(pidl)) { + BOOL bSimplePidl = _ILIsPidlSimple(pidl); + + if (bSimplePidl) { + _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */ + } else { + FIXME("special pidl\n"); + } + + if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { /* go deeper if needed */ + int len = 0; + + PathAddBackslashA(szPath); /*FIXME*/ + len = lstrlenA(szPath); + + if (!SUCCEEDED + (SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len))) + return E_OUTOFMEMORY; + } + } + + strRet->uType = STRRET_CSTR; + lstrcpynA(strRet->u.cStr, szPath, MAX_PATH); + + TRACE("--(%p)->(%s)\n", This, szPath); + return S_OK; +} + +/************************************************************************** +* ISF_ControlPanel_fnSetNameOf +* Changes the name of a file object or subfolder, possibly changing its item +* identifier in the process. +* +* PARAMETERS +* HWND hwndOwner, //[in ] Owner window for output +* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change +* LPCOLESTR lpszName, //[in ] the items new display name +* DWORD dwFlags, //[in ] SHGNO formatting flags +* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned +*/ +static HRESULT WINAPI ISF_ControlPanel_fnSetNameOf(IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ + LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) +{ + ICOM_THIS(ICPanelImpl, iface); + FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut); + return E_FAIL; +} + +static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultSearchGUID(IShellFolder2 * iface, GUID * pguid) +{ + ICOM_THIS(ICPanelImpl, iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_ControlPanel_fnEnumSearches(IShellFolder2 * iface, IEnumExtraSearch ** ppenum) +{ + ICOM_THIS(ICPanelImpl, iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultColumn(IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay) +{ + ICOM_THIS(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + if (pSort) *pSort = 0; + if (pDisplay) *pDisplay = 0; + return S_OK; +} +static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultColumnState(IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) +{ + ICOM_THIS(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + if (!pcsFlags || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) return E_INVALIDARG; + *pcsFlags = ControlPanelSFHeader[iColumn].pcsFlags; + return S_OK; +} +static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsEx(IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) +{ + ICOM_THIS(ICPanelImpl, iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsOf(IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) +{ + ICOM_THIS(ICPanelImpl, iface); + HRESULT hr; + + TRACE("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); + + if (!psd || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) + return E_INVALIDARG; + + if (!pidl) { + psd->fmt = ControlPanelSFHeader[iColumn].fmt; + psd->cxChar = ControlPanelSFHeader[iColumn].cxChar; + psd->str.uType = STRRET_CSTR; + LoadStringA(shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); + return S_OK; + } else { + psd->str.u.cStr[0] = 0x00; + psd->str.uType = STRRET_CSTR; + switch(iColumn) { + case 0: /* name */ + hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); + break; + case 1: /* comment */ + _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH); + break; + } + hr = S_OK; + } + + return hr; +} +static HRESULT WINAPI ISF_ControlPanel_fnMapColumnToSCID(IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) +{ + ICOM_THIS(ICPanelImpl, iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static ICOM_VTABLE(IShellFolder2) vt_ShellFolder2 = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + + ISF_ControlPanel_fnQueryInterface, + ISF_ControlPanel_fnAddRef, + ISF_ControlPanel_fnRelease, + ISF_ControlPanel_fnParseDisplayName, + ISF_ControlPanel_fnEnumObjects, + ISF_ControlPanel_fnBindToObject, + ISF_ControlPanel_fnBindToStorage, + ISF_ControlPanel_fnCompareIDs, + ISF_ControlPanel_fnCreateViewObject, + ISF_ControlPanel_fnGetAttributesOf, + ISF_ControlPanel_fnGetUIObjectOf, + ISF_ControlPanel_fnGetDisplayNameOf, + ISF_ControlPanel_fnSetNameOf, + + /* ShellFolder2 */ + ISF_ControlPanel_fnGetDefaultSearchGUID, + ISF_ControlPanel_fnEnumSearches, + ISF_ControlPanel_fnGetDefaultColumn, + ISF_ControlPanel_fnGetDefaultColumnState, + ISF_ControlPanel_fnGetDetailsEx, + ISF_ControlPanel_fnGetDetailsOf, + ISF_ControlPanel_fnMapColumnToSCID +}; + +/************************************************************************ + * ICPanel_PersistFolder2_QueryInterface + */ +static HRESULT WINAPI ICPanel_PersistFolder2_QueryInterface(IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObject) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + return IUnknown_QueryInterface(_IUnknown_(This), iid, ppvObject); +} + +/************************************************************************ + * ICPanel_PersistFolder2_AddRef + */ +static ULONG WINAPI ICPanel_PersistFolder2_AddRef(IPersistFolder2 * iface) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef(_IUnknown_(This)); +} + +/************************************************************************ + * ISFPersistFolder_Release + */ +static ULONG WINAPI ICPanel_PersistFolder2_Release(IPersistFolder2 * iface) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_Release(_IUnknown_(This)); +} + +/************************************************************************ + * ICPanel_PersistFolder2_GetClassID + */ +static HRESULT WINAPI ICPanel_PersistFolder2_GetClassID(IPersistFolder2 * iface, CLSID * lpClassId) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + if (!lpClassId) + return E_POINTER; + *lpClassId = CLSID_ControlPanel; + + return S_OK; +} + +/************************************************************************ + * ICPanel_PersistFolder2_Initialize + * + * NOTES: it makes no sense to change the pidl + */ +static HRESULT WINAPI ICPanel_PersistFolder2_Initialize(IPersistFolder2 * iface, LPCITEMIDLIST pidl) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + TRACE("(%p)->(%p)\n", This, pidl); + return E_NOTIMPL; +} + +/************************************************************************** + * IPersistFolder2_fnGetCurFolder + */ +static HRESULT WINAPI ICPanel_PersistFolder2_GetCurFolder(IPersistFolder2 * iface, LPITEMIDLIST * pidl) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)->(%p)\n", This, pidl); + + if (!pidl) + return E_POINTER; + *pidl = ILClone(This->pidlRoot); + return S_OK; +} + +static ICOM_VTABLE(IPersistFolder2) vt_PersistFolder2 = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + + ICPanel_PersistFolder2_QueryInterface, + ICPanel_PersistFolder2_AddRef, + ICPanel_PersistFolder2_Release, + ICPanel_PersistFolder2_GetClassID, + ICPanel_PersistFolder2_Initialize, + ICPanel_PersistFolder2_GetCurFolder +}; + +HRESULT WINAPI CPanel_GetIconLocationA(LPITEMIDLIST pidl, LPSTR szIconFile, UINT cchMax, int* piIndex) +{ + PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl); + + if (!pcpanel) + return E_INVALIDARG; + + lstrcpyA(szIconFile, pcpanel->szName); + *piIndex = pcpanel->iconIdx!=-1? pcpanel->iconIdx: 0; + + return S_OK; +} + +HRESULT WINAPI CPanel_GetIconLocationW(LPITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex) +{ + PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl); + + if (!pcpanel) + return E_INVALIDARG; + + MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, szIconFile, cchMax); + *piIndex = pcpanel->iconIdx!=-1? pcpanel->iconIdx: 0; + + return S_OK; +} + + +/************************************************************************** +* IShellExecuteHookW Implementation +*/ + +static HRESULT WINAPI IShellExecuteHookW_fnQueryInterface(IShellExecuteHookW* iface, REFIID riid, void** ppvObject) +{ + _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookW_fnAddRef(IShellExecuteHookW* iface) +{ + _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef(This->pUnkOuter); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookW_fnRelease(IShellExecuteHookW* iface) +{ + _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + return IUnknown_Release(This->pUnkOuter); +} + +static HRESULT WINAPI IShellExecuteHookW_fnExecute(IShellExecuteHookW* iface, LPSHELLEXECUTEINFOW psei) +{ + ICOM_THIS(ICPanelImpl, iface); + + SHELLEXECUTEINFOW sei_tmp; + PIDLCPanelStruct* pcpanel; + WCHAR path[MAX_PATH]; + BOOL ret; + int l; + + TRACE("(%p)->execute(%p)\n", This, psei); + + if (!psei) + return E_INVALIDARG; + + pcpanel = _ILGetCPanelPointer(ILFindLastID(psei->lpIDList)); + + if (!pcpanel) + return E_INVALIDARG; + + path[0] = '\"'; + l = 1 + MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, path+1, MAX_PATH); + + /* pass applet name to Control_RunDLL to distinguish between applets in one .cpl file */ + path[++l] = '"'; + path[++l] = ' '; + + MultiByteToWideChar(CP_ACP, 0, pcpanel->szName+pcpanel->offsDispName, -1, path+l, MAX_PATH); + + memcpy(&sei_tmp, psei, sizeof(sei_tmp)); + sei_tmp.lpFile = path; + sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; + + ret = ShellExecuteExW(&sei_tmp); + if (ret) + return S_OK; + else + return S_FALSE; +} + +static ICOM_VTABLE(IShellExecuteHookW) vt_ShellExecuteHookW = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + + IShellExecuteHookW_fnQueryInterface, + IShellExecuteHookW_fnAddRef, + IShellExecuteHookW_fnRelease, + + IShellExecuteHookW_fnExecute +}; + + +/************************************************************************** +* IShellExecuteHookA Implementation +*/ + +static HRESULT WINAPI IShellExecuteHookA_fnQueryInterface(IShellExecuteHookA* iface, REFIID riid, void** ppvObject) +{ + _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookA_fnAddRef(IShellExecuteHookA* iface) +{ + _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef(This->pUnkOuter); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookA_fnRelease(IShellExecuteHookA* iface) +{ + _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + return IUnknown_Release(This->pUnkOuter); +} + +static HRESULT WINAPI IShellExecuteHookA_fnExecute(IShellExecuteHookA* iface, LPSHELLEXECUTEINFOA psei) +{ + ICOM_THIS(ICPanelImpl, iface); + + SHELLEXECUTEINFOA sei_tmp; + PIDLCPanelStruct* pcpanel; + char path[MAX_PATH]; + BOOL ret; + + TRACE("(%p)->execute(%p)\n", This, psei); + + if (!psei) + return E_INVALIDARG; + + pcpanel = _ILGetCPanelPointer(ILFindLastID(psei->lpIDList)); + + if (!pcpanel) + return E_INVALIDARG; + + path[0] = '\"'; + lstrcpyA(path+1, pcpanel->szName); + + /* pass applet name to Control_RunDLL to distinguish between applets in one .cpl file */ + lstrcatA(path, "\" "); + lstrcatA(path, pcpanel->szName+pcpanel->offsDispName); + + memcpy(&sei_tmp, psei, sizeof(sei_tmp)); + sei_tmp.lpFile = path; + sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; + + ret = ShellExecuteExA(&sei_tmp); + if (ret) + return S_OK; + else + return S_FALSE; +} + +static ICOM_VTABLE(IShellExecuteHookA) vt_ShellExecuteHookA = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + + IShellExecuteHookA_fnQueryInterface, + IShellExecuteHookA_fnAddRef, + IShellExecuteHookA_fnRelease, + + IShellExecuteHookA_fnExecute +}; diff --git a/dlls/shell32/enumidlist.c b/dlls/shell32/enumidlist.c index 283a5dce6b8..57cc4023d7d 100644 --- a/dlls/shell32/enumidlist.c +++ b/dlls/shell32/enumidlist.c @@ -29,10 +29,12 @@ #include "shlwapi.h" #include "winerror.h" #include "objbase.h" +#include #include "pidl.h" #include "shlguid.h" #include "shell32_main.h" +#include "cpanel.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); @@ -168,6 +170,161 @@ static BOOL CreateFolderEnumList( return TRUE; } +BOOL SHELL_RegisterCPanelApp(IEnumIDList* list, LPCSTR path) +{ + LPITEMIDLIST pidl; + CPlApplet* applet; + CPanel panel; + CPLINFO info; + unsigned i; + int iconIdx; + + char displayName[MAX_PATH]; + char comment[MAX_PATH]; + + WCHAR wpath[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); + + panel.first = NULL; + applet = Control_LoadApplet(0, wpath, &panel); + + if (applet) { + for(i=0; icount; ++i) { + WideCharToMultiByte(CP_ACP, 0, applet->info[i].szName, -1, displayName, MAX_PATH, 0, 0); + WideCharToMultiByte(CP_ACP, 0, applet->info[i].szInfo, -1, comment, MAX_PATH, 0, 0); + + applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info); + + if (info.idIcon > 0) + iconIdx = -info.idIcon; /* negative icon index instead of icon number */ + else + iconIdx = 0; + + pidl = _ILCreateCPanel(path, displayName, comment, iconIdx); + + if (pidl) + AddToEnumList(list, pidl); + } + + Control_UnloadApplet(applet); + } + + return TRUE; +} + +int SHELL_RegisterRegistryCPanelApps(IEnumIDList* list, HKEY hkey_root, LPCSTR szRepPath) +{ + char name[MAX_PATH]; + char value[MAX_PATH]; + HKEY hkey; + + int cnt = 0; + + if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) + { + int idx = 0; + for(;; ++idx) + { + DWORD nameLen = MAX_PATH; + DWORD valueLen = MAX_PATH; + + if (RegEnumValueA(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS) + break; + + if (SHELL_RegisterCPanelApp(list, value)) + ++cnt; + } + + RegCloseKey(hkey); + } + + return cnt; +} + +int SHELL_RegisterCPanelFolders(IEnumIDList* list, HKEY hkey_root, LPCSTR szRepPath) +{ + char name[MAX_PATH]; + HKEY hkey; + + int cnt = 0; + + if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) + { + int idx = 0; + for(;; ++idx) + { + if (RegEnumKeyA(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS) + break; + + if (*name == '{') { + LPITEMIDLIST pidl = _ILCreateSpecial(name); + + if (pidl && AddToEnumList(list, pidl)) + ++cnt; + } + } + + RegCloseKey(hkey); + } + + return cnt; +} + +/************************************************************************** + * CreateCPanelEnumList() + */ +static BOOL CreateCPanelEnumList( + IEnumIDList * iface, + DWORD dwFlags) +{ + ICOM_THIS(IEnumIDListImpl,iface); + + CHAR szPath[MAX_PATH]; + WIN32_FIND_DATAA wfd; + HANDLE hFile; + + TRACE("(%p)->(flags=0x%08lx) \n",This,dwFlags); + + /* enumerate control panel folders folders */ + if (dwFlags & SHCONTF_FOLDERS) + SHELL_RegisterCPanelFolders((IEnumIDList*)This, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace"); + + /* enumerate the control panel applets */ + if (dwFlags & SHCONTF_NONFOLDERS) + { + LPSTR p; + + GetSystemDirectoryA(szPath, MAX_PATH); + p = PathAddBackslashA(szPath); + strcpy(p, "*.cpl"); + + TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",This,debugstr_a(szPath)); + hFile = FindFirstFileA(szPath, &wfd); + + if (hFile != INVALID_HANDLE_VALUE) + { + do + { + if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) + continue; + + if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + strcpy(p, wfd.cFileName); + SHELL_RegisterCPanelApp((IEnumIDList*)This, szPath); + } + } while(FindNextFileA(hFile, &wfd)); + + FindClose(hFile); + } + + SHELL_RegisterRegistryCPanelApps((IEnumIDList*)This, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); + SHELL_RegisterRegistryCPanelApps((IEnumIDList*)This, HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); + } + + return TRUE; +} + /************************************************************************** * CreateDesktopEnumList() */ @@ -343,6 +500,10 @@ IEnumIDList * IEnumIDList_Constructor( case EIDL_FILE: ret = CreateFolderEnumList((IEnumIDList*)lpeidl, lpszPath, dwFlags); break; + + case EIDL_CPANEL: + ret = CreateCPanelEnumList((IEnumIDList*)lpeidl, dwFlags); + break; } if(!ret) { diff --git a/dlls/shell32/folders.c b/dlls/shell32/folders.c index a4ef4384f2b..055466677ab 100644 --- a/dlls/shell32/folders.c +++ b/dlls/shell32/folders.c @@ -231,33 +231,47 @@ static HRESULT WINAPI IExtractIconW_fnGetIconLocation( } *piIndex = (uFlags & GIL_OPENICON) ? dwNr + 1 : dwNr; } - else /* object is file */ + + else { - if (_ILGetExtension(pSimplePidl, sTemp, MAX_PATH) - && HCR_MapTypeToValueA(sTemp, sTemp, MAX_PATH, TRUE) - && HCR_GetDefaultIconA(sTemp, sTemp, MAX_PATH, &dwNr)) + BOOL found = FALSE; + + if (_ILIsCPanelStruct(pSimplePidl)) { - if (!lstrcmpA("%1", sTemp)) /* icon is in the file */ + if (SUCCEEDED(CPanel_GetIconLocationW(pSimplePidl, szIconFile, cchMax, piIndex))) + found = TRUE; + } + else if (_ILGetExtension(pSimplePidl, sTemp, MAX_PATH)) + { + if (HCR_MapTypeToValueA(sTemp, sTemp, MAX_PATH, TRUE) + && HCR_GetDefaultIconA(sTemp, sTemp, MAX_PATH, &dwNr)) { - SHGetPathFromIDListW(This->pidl, szIconFile); + if (!lstrcmpA("%1", sTemp)) /* icon is in the file */ + { + SHGetPathFromIDListW(This->pidl, szIconFile); + *piIndex = 0; + } + else + { + MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax); + *piIndex = dwNr; + } + + found = TRUE; + } + + if (!found) /* default icon */ + { + lstrcpynW(szIconFile, swShell32Name, cchMax); *piIndex = 0; } - else - { - MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax); - *piIndex = dwNr; - } - } - else /* default icon */ - { - lstrcpynW(szIconFile, swShell32Name, cchMax); - *piIndex = 0; } } TRACE("-- %s %x\n", debugstr_w(szIconFile), *piIndex); return NOERROR; } + /************************************************************************** * IExtractIconW_Extract */ diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c index f511bd5cafb..af380d7bd14 100644 --- a/dlls/shell32/pidl.c +++ b/dlls/shell32/pidl.c @@ -1662,6 +1662,49 @@ LPITEMIDLIST _ILCreateSpecial(LPCSTR szGUID) return _ILCreate(PT_MYCOMP, &iid, sizeof(IID)); } +LPITEMIDLIST _ILCreateCPanel(LPCSTR name, LPCSTR displayName, LPCSTR comment, int iconIdx) +{ + PIDLCPanelStruct *p; + LPITEMIDLIST pidl; + PIDLDATA tmp; + int size0 = (char*)&tmp.u.cpanel.szName-(char*)&tmp.u.cpanel; + int size = size0; + int l; + + tmp.type = 0; + tmp.u.cpanel.dummy = 0; + tmp.u.cpanel.iconIdx = iconIdx; + + l = strlen(name); + size += l+1; + + tmp.u.cpanel.offsDispName = l+1; + l = strlen(displayName); + size += l+1; + + tmp.u.cpanel.offsComment = tmp.u.cpanel.offsDispName+1+l; + l = strlen(comment); + size += l+1; + + pidl = SHAlloc(size+4); + if (!pidl) + return NULL; + + pidl->mkid.cb = size+2; + memcpy(pidl->mkid.abID, &tmp, 2+size0); + + p = &((PIDLDATA*)pidl->mkid.abID)->u.cpanel; + strcpy(p->szName, name); + strcpy(p->szName+tmp.u.cpanel.offsDispName, displayName); + strcpy(p->szName+tmp.u.cpanel.offsComment, comment); + + *(WORD*)((char*)pidl+(size+2)) = 0; + + pcheck(pidl); + + return pidl; +} + /************************************************************************** * _ILCreate() * Creates a new PIDL @@ -1823,6 +1866,12 @@ BOOL _ILIsValue(LPCITEMIDLIST pidl) return (pidl && lpPData && PT_VALUE == lpPData->type); } +BOOL _ILIsCPanelStruct(LPCITEMIDLIST pidl) +{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); + TRACE("(%p)\n",pidl); + return (pidl && lpPData && (lpPData->type == 0)); +} + /************************************************************************** * _ILIsPidlSimple */ @@ -2041,6 +2090,20 @@ REFIID _ILGetGUIDPointer(LPCITEMIDLIST pidl) return NULL; } +/************************************************************************** + * _ILGetCPanelPointer() + * gets a pointer to the control panel struct stored in the pidl + */ +PIDLCPanelStruct* _ILGetCPanelPointer(LPCITEMIDLIST pidl) +{ + LPPIDLDATA pdata = _ILGetDataPointer(pidl); + + if (pdata && pdata->type==0) + return (PIDLCPanelStruct*)&(pdata->u.cpanel); + + return NULL; +} + /************************************************************************* * _ILGetFileDateTime * diff --git a/dlls/shell32/pidl.h b/dlls/shell32/pidl.h index bf8f33e5a04..0b73bc0b6be 100644 --- a/dlls/shell32/pidl.h +++ b/dlls/shell32/pidl.h @@ -107,6 +107,15 @@ #include "pshpack1.h" typedef BYTE PIDLTYPE; +typedef struct tagPIDLCPanelStruct +{ + BYTE dummy; /*01 is 0x00 */ + DWORD iconIdx; /*02 negative icon ID */ + WORD offsDispName; /*06*/ + WORD offsComment; /*08*/ + CHAR szName[1]; /*10*/ /* terminated by 0x00, followed by display name and comment string */ +} PIDLCPanelStruct; + typedef struct tagPIDLDATA { PIDLTYPE type; /*00*/ union @@ -137,8 +146,9 @@ typedef struct tagPIDLDATA struct { WORD dummy; /*01*/ DWORD dummy1; /*02*/ - CHAR szName[1]; /*06*/ /* teminated by 0x00 0x00 */ + CHAR szName[1]; /*06*/ /* terminated by 0x00 0x00 */ } htmlhelp; + struct tagPIDLCPanelStruct cpanel; }u; } PIDLDATA, *LPPIDLDATA; #include "poppack.h" @@ -167,6 +177,7 @@ BOOL _ILIsFolder (LPCITEMIDLIST pidl); BOOL _ILIsValue (LPCITEMIDLIST pidl); BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl); BOOL _ILIsPidlSimple (LPCITEMIDLIST pidl); +BOOL _ILIsCPanelStruct (LPCITEMIDLIST pidl); /* * simple pidls from strings @@ -185,6 +196,7 @@ LPITEMIDLIST _ILCreateFolder (WIN32_FIND_DATAA * stffile); LPITEMIDLIST _ILCreateValue (WIN32_FIND_DATAA * stffile); LPITEMIDLIST _ILCreateSpecial (LPCSTR szGUID); LPITEMIDLIST _ILCreateFromPathA (LPCSTR szPath); +LPITEMIDLIST _ILCreateCPanel (LPCSTR name, LPCSTR displayName, LPCSTR comment, int iconIdx); /* * helper functions (getting struct-pointer) @@ -193,6 +205,7 @@ LPPIDLDATA _ILGetDataPointer (LPCITEMIDLIST); LPSTR _ILGetTextPointer (LPCITEMIDLIST); LPSTR _ILGetSTextPointer (LPCITEMIDLIST); REFIID _ILGetGUIDPointer (LPCITEMIDLIST pidl); +PIDLCPanelStruct* _ILGetCPanelPointer (LPCITEMIDLIST pidl); /* * debug helper diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h index faab01187b9..7a6ec7f5992 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -91,11 +91,17 @@ HRESULT WINAPI ISF_Desktop_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID HRESULT WINAPI ISF_MyComputer_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV); +HRESULT WINAPI IControlPanel_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); +HRESULT WINAPI CPanel_GetIconLocationA(LPITEMIDLIST pidl, LPSTR szIconFile, UINT cchMax, int* piIndex); +HRESULT WINAPI CPanel_GetIconLocationW(LPITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex); +HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); +HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); /* kind of enumidlist */ #define EIDL_DESK 0 #define EIDL_MYCOMP 1 #define EIDL_FILE 2 +#define EIDL_CPANEL 3 LPENUMIDLIST IEnumIDList_Constructor(LPCSTR,DWORD,DWORD); diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c index 85a21b41078..5ffed9b2d42 100644 --- a/dlls/shell32/shellole.c +++ b/dlls/shell32/shellole.c @@ -61,12 +61,13 @@ IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, struct { REFIID riid; LPFNCREATEINSTANCE lpfnCI; -} InterfaceTable[6] = { +} InterfaceTable[] = { {&CLSID_ShellFSFolder, &IFSFolder_Constructor}, {&CLSID_MyComputer, &ISF_MyComputer_Constructor}, {&CLSID_ShellDesktop, &ISF_Desktop_Constructor}, {&CLSID_ShellLink, &IShellLink_Constructor}, {&CLSID_DragDropHelper, &IDropTargetHelper_Constructor}, + {&CLSID_ControlPanel, &IControlPanel_Constructor}, {NULL,NULL} };