Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954/* * Control panel folder * * Copyright 2003 Martin Fuchs * Copyright 2009 Andrew Hill * * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include <precomp.h>
WINE_DEFAULT_DEBUG_CHANNEL(shell);
static const REGFOLDERINFO g_RegFolderInfo ={ PT_CONTROLS_NEWREGITEM, 0, NULL, CLSID_ControlPanel, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", L"ControlPanel",};
/************************************************************************ control panel implementation in shell namespace*/
class CControlPanelEnum : public CEnumIDListBase{ public: CControlPanelEnum(); ~CControlPanelEnum(); HRESULT WINAPI Initialize(DWORD dwFlags, IEnumIDList* pRegEnumerator); BOOL RegisterCPanelApp(LPCWSTR path); int RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath); BOOL CreateCPanelEnumList(DWORD dwFlags);
BEGIN_COM_MAP(CControlPanelEnum) COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList) END_COM_MAP()};
/************************************************************************ IShellFolder [ControlPanel] implementation*/
static const shvheader ControlPanelSFHeader[] = { {IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 20},/*FIXME*/ {IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 80},/*FIXME*/};
enum controlpanel_columns{ CONTROLPANEL_COL_NAME, CONTROLPANEL_COL_COMMENT, CONTROLPANEL_COL_COUNT,};
CControlPanelEnum::CControlPanelEnum(){}
CControlPanelEnum::~CControlPanelEnum(){}
HRESULT WINAPI CControlPanelEnum::Initialize(DWORD dwFlags, IEnumIDList* pRegEnumerator){ if (CreateCPanelEnumList(dwFlags) == FALSE) return E_FAIL; AppendItemsFromEnumerator(pRegEnumerator); return S_OK;}
static const CLSID* IsRegItem(LPCITEMIDLIST pidl){ BYTE type = _ILGetType(pidl); if (type == PT_CONTROLS_OLDREGITEM || type == PT_CONTROLS_NEWREGITEM) return (CLSID*)((BYTE*)pidl + (pidl->mkid.cb - sizeof(CLSID))); return NULL;}
static LPITEMIDLIST _ILCreateCPanelApplet(LPCWSTR pszName, LPCWSTR pszDisplayName, LPCWSTR pszComment, int iIconIdx){ PIDLCPanelStruct *pCP; LPITEMIDLIST pidl; LPPIDLDATA pData; int cchName, cchDisplayName, cchComment, cbData;
/* Calculate lengths of given strings */ cchName = wcslen(pszName); cchDisplayName = wcslen(pszDisplayName); cchComment = wcslen(pszComment);
/* Allocate PIDL */ cbData = sizeof(pidl->mkid.cb) + sizeof(pData->type) + sizeof(pData->u.cpanel) - sizeof(pData->u.cpanel.szName) + (cchName + cchDisplayName + cchComment + 3) * sizeof(WCHAR); pidl = (LPITEMIDLIST)SHAlloc(cbData + sizeof(WORD)); if (!pidl) return NULL;
/* Copy data to allocated memory */ pidl->mkid.cb = cbData; pData = (PIDLDATA *)pidl->mkid.abID; pData->type = PT_CPLAPPLET;
pCP = &pData->u.cpanel; pCP->dummy = 0; pCP->iconIdx = iIconIdx; wcscpy(pCP->szName, pszName); pCP->offsDispName = cchName + 1; wcscpy(pCP->szName + pCP->offsDispName, pszDisplayName); pCP->offsComment = pCP->offsDispName + cchDisplayName + 1; wcscpy(pCP->szName + pCP->offsComment, pszComment);
/* Add PIDL NULL terminator */ *(WORD*)(pCP->szName + pCP->offsComment + cchComment + 1) = 0;
pcheck(pidl);
return pidl;}
/************************************************************************** * _ILGetCPanelPointer() * gets a pointer to the control panel struct stored in the pidl */static PIDLCPanelStruct *_ILGetCPanelPointer(LPCITEMIDLIST pidl){ LPPIDLDATA pdata = _ILGetDataPointer(pidl);
if (pdata && pdata->type == PT_CPLAPPLET) return (PIDLCPanelStruct *) & (pdata->u.cpanel);
return NULL;}
HRESULT CCPLExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut){ PIDLCPanelStruct *pData = _ILGetCPanelPointer(pidl); if (!pData) return E_FAIL;
CComPtr<IDefaultExtractIconInit> initIcon; HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); if (FAILED_UNEXPECTEDLY(hr)) return hr;
initIcon->SetNormalIcon(pData->szName, (int)pData->iconIdx != -1 ? pData->iconIdx : 0);
return initIcon->QueryInterface(riid, ppvOut);}
BOOL CControlPanelEnum::RegisterCPanelApp(LPCWSTR wpath){ CPlApplet* applet = Control_LoadApplet(0, wpath, NULL); int iconIdx;
if (applet) { for (UINT i = 0; i < applet->count; ++i) { if (applet->info[i].idIcon > 0) iconIdx = -applet->info[i].idIcon; /* negative icon index instead of icon number */ else iconIdx = 0;
LPITEMIDLIST pidl = _ILCreateCPanelApplet(wpath, applet->info[i].name, applet->info[i].info, iconIdx);
if (pidl) AddToEnumList(pidl); } Control_UnloadApplet(applet); } return TRUE;}
int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath){ WCHAR name[MAX_PATH]; WCHAR value[MAX_PATH]; HKEY hkey;
int cnt = 0;
if (RegOpenKeyW(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) { int idx = 0;
for(; ; idx++) { DWORD nameLen = MAX_PATH; DWORD valueLen = MAX_PATH; WCHAR buffer[MAX_PATH];
if (RegEnumValueW(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS) break;
if (ExpandEnvironmentStringsW(value, buffer, MAX_PATH)) { wcscpy(value, buffer); }
if (RegisterCPanelApp(value)) ++cnt; } RegCloseKey(hkey); }
return cnt;}
/************************************************************************** * CControlPanelEnum::CreateCPanelEnumList() */BOOL CControlPanelEnum::CreateCPanelEnumList(DWORD dwFlags){ WCHAR szPath[MAX_PATH]; WIN32_FIND_DATAW wfd; HANDLE hFile;
TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
/* enumerate the control panel applets */ if (dwFlags & SHCONTF_NONFOLDERS) { LPWSTR p;
GetSystemDirectoryW(szPath, MAX_PATH); p = PathAddBackslashW(szPath); wcscpy(p, L"*.cpl");
hFile = FindFirstFileW(szPath, &wfd);
if (hFile != INVALID_HANDLE_VALUE) { do { if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) continue;
if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { wcscpy(p, wfd.cFileName); if (wcscmp(wfd.cFileName, L"ncpa.cpl")) RegisterCPanelApp(szPath); } } while(FindNextFileW(hFile, &wfd)); FindClose(hFile); }
RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); RegisterRegistryCPanelApps(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); } return TRUE;}
CControlPanelFolder::CControlPanelFolder(){ pidlRoot = NULL; /* absolute pidl */}
CControlPanelFolder::~CControlPanelFolder(){ TRACE("-- destroying IShellFolder(%p)\n", this); SHFree(pidlRoot);}
/*************************************************************************** CControlPanelFolder::ParseDisplayName*/HRESULT WINAPI CControlPanelFolder::ParseDisplayName( HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes){ /* We only support parsing guid names */ return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);}
/*************************************************************************** CControlPanelFolder::EnumObjects*/HRESULT WINAPI CControlPanelFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList){ CComPtr<IEnumIDList> pRegEnumerator; m_regFolder->EnumObjects(hwndOwner, dwFlags, &pRegEnumerator);
return ShellObjectCreatorInit<CControlPanelEnum>(dwFlags, pRegEnumerator, IID_PPV_ARG(IEnumIDList, ppEnumIDList));}
/*************************************************************************** CControlPanelFolder::BindToObject*/HRESULT WINAPI CControlPanelFolder::BindToObject( PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut){ return m_regFolder->BindToObject(pidl, pbcReserved, riid, ppvOut);}
/*************************************************************************** CControlPanelFolder::BindToStorage*/HRESULT WINAPI CControlPanelFolder::BindToStorage( PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut){ FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
*ppvOut = NULL; return E_NOTIMPL;}
/*************************************************************************** CControlPanelFolder::CompareIDs*/HRESULT WINAPI CControlPanelFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2){ /* Dont use SHELL32_CompareGuidItems because it would cause guid items to come first */ if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2)) { return SHELL32_CompareDetails(this, lParam, pidl1, pidl2); } PIDLCPanelStruct *pData1 = _ILGetCPanelPointer(pidl1); PIDLCPanelStruct *pData2 = _ILGetCPanelPointer(pidl2);
if (!pData1 || !pData2 || LOWORD(lParam) >= CONTROLPANEL_COL_COUNT) return E_INVALIDARG;
int result; switch(LOWORD(lParam)) { case CONTROLPANEL_COL_NAME: result = SHELL_StrCmpLogical(pData1->szName + pData1->offsDispName, pData2->szName + pData2->offsDispName); break; case CONTROLPANEL_COL_COMMENT: result = SHELL_StrCmpLogical(pData1->szName + pData1->offsComment, pData2->szName + pData2->offsComment); break; default: ERR("Got wrong lParam!\n"); return E_INVALIDARG; }
return MAKE_COMPARE_HRESULT(result);}
/*************************************************************************** CControlPanelFolder::CreateViewObject*/HRESULT WINAPI CControlPanelFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut){ CComPtr<IShellView> 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)) { SFV_CREATE sfvparams = { sizeof(SFV_CREATE), this , NULL, this }; hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut); } } TRACE("--(%p)->(interface=%p)\n", this, ppvOut); return hr;}
/*************************************************************************** CControlPanelFolder::GetAttributesOf*/HRESULT WINAPI CControlPanelFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut){ HRESULT hr = S_OK; static const DWORD dwControlPanelAttributes = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK;
TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
if (!rgfInOut) return E_INVALIDARG; if (cidl && !apidl) return E_INVALIDARG;
if (*rgfInOut == 0) *rgfInOut = ~0;
if (!cidl) { *rgfInOut &= dwControlPanelAttributes; } else { while(cidl > 0 && *apidl) { pdump(*apidl); if (_ILIsCPanelStruct(*apidl)) *rgfInOut &= SFGAO_CANLINK; else if (_ILIsSpecialFolder(*apidl)) m_regFolder->GetAttributesOf(1, apidl, rgfInOut); else ERR("Got unknown pidl\n"); apidl++; cidl--; } } /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */ *rgfInOut &= ~SFGAO_VALIDATE;
TRACE("-- result=0x%08x\n", *rgfInOut); return hr;}
/*************************************************************************** CControlPanelFolder::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**/HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut){ LPVOID 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)) { /* HACK: We should use callbacks from CDefaultContextMenu instead of creating one on our own */ BOOL bHasCpl = FALSE; for (UINT i = 0; i < cidl; i++) { if(_ILIsCPanelStruct(apidl[i])) { bHasCpl = TRUE; } }
if (bHasCpl) hr = ShellObjectCreatorInit<CCPLItemMenu>(cidl, apidl, riid, &pObj); else hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj); } else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) { hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, TRUE, (IDataObject **)&pObj); } else if ((IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && (cidl == 1)) { if (_ILGetCPanelPointer(apidl[0])) hr = CCPLExtractIcon_CreateInstance(this, apidl[0], riid, &pObj); else hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj); } else { hr = E_NOINTERFACE; }
if (SUCCEEDED(hr) && !pObj) hr = E_OUTOFMEMORY;
*ppvOut = pObj; } TRACE("(%p)->hr=0x%08x\n", this, hr); return hr;}
/*************************************************************************** CControlPanelFolder::GetDisplayNameOf*/HRESULT WINAPI CControlPanelFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet){ if (!pidl) return S_FALSE;
PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(pidl);
if (pCPanel) { return SHSetStrRet(strRet, pCPanel->szName + pCPanel->offsDispName); } else if (_ILIsSpecialFolder(pidl)) { return m_regFolder->GetDisplayNameOf(pidl, dwFlags, strRet); }
return E_FAIL;}
/*************************************************************************** CControlPanelFolder::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*/HRESULT WINAPI CControlPanelFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /*simple pidl */ LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut){ FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut); return E_FAIL;}
HRESULT WINAPI CControlPanelFolder::GetDefaultSearchGUID(GUID *pguid){ FIXME("(%p)\n", this); return E_NOTIMPL;}
HRESULT WINAPI CControlPanelFolder::EnumSearches(IEnumExtraSearch **ppenum){ FIXME("(%p)\n", this); return E_NOTIMPL;}
HRESULT WINAPI CControlPanelFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay){ TRACE("(%p)\n", this);
if (pSort) *pSort = 0; if (pDisplay) *pDisplay = 0; return S_OK;}
HRESULT WINAPI CControlPanelFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags){ TRACE("(%p)\n", this);
if (!pcsFlags || iColumn >= CONTROLPANEL_COL_COUNT) return E_INVALIDARG; *pcsFlags = ControlPanelSFHeader[iColumn].colstate; return S_OK;}
HRESULT WINAPI CControlPanelFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv){ if (IsRegItem(pidl)) return m_regFolder->GetDetailsEx(pidl, pscid, pv); return SH32_GetDetailsOfPKeyAsVariant(this, pidl, pscid, pv, FALSE);}
HRESULT WINAPI CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd){ if (!psd || iColumn >= CONTROLPANEL_COL_COUNT) return E_INVALIDARG;
if (!pidl) { psd->fmt = ControlPanelSFHeader[iColumn].fmt; psd->cxChar = ControlPanelSFHeader[iColumn].cxChar; return SHSetStrRet(&psd->str, shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid); } else if (_ILIsSpecialFolder(pidl)) { return m_regFolder->GetDetailsOf(pidl, iColumn, psd); } else { PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(pidl);
if (!pCPanel) return E_FAIL;
switch(iColumn) { case CONTROLPANEL_COL_NAME: return SHSetStrRet(&psd->str, pCPanel->szName + pCPanel->offsDispName); case CONTROLPANEL_COL_COMMENT: return SHSetStrRet(&psd->str, pCPanel->szName + pCPanel->offsComment); } }
return E_FAIL;}
HRESULT WINAPI CControlPanelFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid){ switch (column) { case CONTROLPANEL_COL_NAME: return MakeSCID(*pscid, FMTID_Storage, PID_STG_NAME); case CONTROLPANEL_COL_COMMENT: return MakeSCID(*pscid, FMTID_SummaryInformation, PIDSI_COMMENTS); } return E_INVALIDARG;}
/************************************************************************ * CControlPanelFolder::GetClassID */HRESULT WINAPI CControlPanelFolder::GetClassID(CLSID *lpClassId){ TRACE("(%p)\n", this);
if (!lpClassId) return E_POINTER; *lpClassId = CLSID_ControlPanel;
return S_OK;}
/************************************************************************ * CControlPanelFolder::Initialize * * NOTES: it makes no sense to change the pidl */HRESULT WINAPI CControlPanelFolder::Initialize(PCIDLIST_ABSOLUTE pidl){ if (pidlRoot) SHFree((LPVOID)pidlRoot);
pidlRoot = ILClone(pidl);
/* Create the inner reg folder */ REGFOLDERINITDATA RegInit = { static_cast<IShellFolder*>(this), &g_RegFolderInfo }; HRESULT hr; hr = CRegFolder_CreateInstance(&RegInit, pidlRoot, IID_PPV_ARG(IShellFolder2, &m_regFolder)); if (FAILED_UNEXPECTEDLY(hr)) return hr;
return S_OK;}
/************************************************************************** * CControlPanelFolder::GetCurFolder */HRESULT WINAPI CControlPanelFolder::GetCurFolder(PIDLIST_ABSOLUTE * pidl){ TRACE("(%p)->(%p)\n", this, pidl);
if (!pidl) return E_POINTER; *pidl = ILClone(pidlRoot); return S_OK;}
HRESULT WINAPI CControlPanelFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { case SFVM_DEFVIEWMODE: { #if ROSPOLICY_CONTROLSFOLDER_DEFLARGEICONS *((FOLDERVIEWMODE*)lParam) = FVM_ICON; #else *((FOLDERVIEWMODE*)lParam) = IsOS(OS_SERVERADMINUI) ? FVM_LIST : FVM_ICON; #endif return S_OK; } } return E_NOTIMPL;}
CCPLItemMenu::CCPLItemMenu(){ m_apidl = NULL; m_cidl = 0;}
HRESULT WINAPI CCPLItemMenu::Initialize(UINT cidl, PCUITEMID_CHILD_ARRAY apidl){ m_cidl = cidl; m_apidl = _ILCopyaPidl(apidl, m_cidl); if (m_cidl && !m_apidl) return E_OUTOFMEMORY;
return S_OK;}
CCPLItemMenu::~CCPLItemMenu(){ _ILFreeaPidl(m_apidl, m_cidl);}
HRESULT WINAPI CCPLItemMenu::QueryContextMenu( HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags){ _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst, MFT_STRING, MAKEINTRESOURCEW(IDS_OPEN), MFS_DEFAULT); _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDC_STATIC, MFT_SEPARATOR, NULL, MFS_ENABLED); _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 1, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED);
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 2);}
EXTERN_Cvoid WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
/*************************************************************************** ICPanel_IContextMenu_InvokeCommand()*/HRESULT WINAPI CCPLItemMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi){ HRESULT hResult;
PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(m_apidl[0]); if(!pCPanel) return E_FAIL;
TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
if (lpcmi->lpVerb == MAKEINTRESOURCEA(0)) { /* Hardcode the command here; Executing a cpl file would be fine but we also need to run things like console.dll */ WCHAR wszParams[MAX_PATH]; PCWSTR wszFile = L"rundll32.exe"; PCWSTR wszFormat = L"shell32.dll,Control_RunDLL %s,%s";
wsprintfW(wszParams, wszFormat, pCPanel->szName, pCPanel->szName + pCPanel->offsDispName);
/* Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */ ShellExecuteW(NULL, NULL, wszFile, wszParams, NULL, 0); } else if (lpcmi->lpVerb == MAKEINTRESOURCEA(1)) //FIXME { CComPtr<IDataObject> pDataObj; LPITEMIDLIST pidl = _ILCreateControlPanel();
hResult = SHCreateDataObject(pidl, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj)); if (FAILED(hResult)) return hResult;
SHFree(pidl);
//FIXME: Use SHCreateLinks CComPtr<IShellFolder> psf; CComPtr<IDropTarget> pDT;
hResult = SHGetDesktopFolder(&psf); if (FAILED(hResult)) return hResult;
hResult = psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pDT)); if (FAILED(hResult)) return hResult;
SHSimulateDrop(pDT, pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL); } return S_OK;}
/************************************************************************** * ICPanel_IContextMenu_GetCommandString() * */HRESULT WINAPI CCPLItemMenu::GetCommandString( UINT_PTR idCommand, UINT uFlags, UINT* lpReserved, LPSTR lpszName, UINT uMaxNameLen){ TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
FIXME("unknown command string\n"); return E_FAIL;}
/*************************************************************************** ICPanel_IContextMenu_HandleMenuMsg()*/HRESULT WINAPI CCPLItemMenu::HandleMenuMsg( UINT uMsg, WPARAM wParam, LPARAM lParam){ TRACE("ICPanel_IContextMenu_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
return E_NOTIMPL;}
/*************************************************************************** COpenControlPanel*/
static HRESULT GetParsingName(PCIDLIST_ABSOLUTE pidl, PWSTR*Name){ PIDLIST_ABSOLUTE pidlFree = NULL; if (IS_INTRESOURCE(pidl)) { HRESULT hr = SHGetSpecialFolderLocation(NULL, (UINT)(SIZE_T)pidl, &pidlFree); if (FAILED(hr)) return hr; pidl = pidlFree; } HRESULT hr = SHGetNameFromIDList(pidl, SIGDN_DESKTOPABSOLUTEPARSING, Name); ILFree(pidlFree); return hr;}
static HRESULT CreateCplAbsoluteParsingPath(LPCWSTR Prefix, LPCWSTR InFolderParse, PWSTR Buf, UINT cchBuf){ PWSTR cpfolder; HRESULT hr = GetParsingName((PCIDLIST_ABSOLUTE)CSIDL_CONTROLS, &cpfolder); if (SUCCEEDED(hr)) { hr = StringCchPrintfW(Buf, cchBuf, L"%s\\%s%s", cpfolder, Prefix, InFolderParse); SHFree(cpfolder); } return hr;}
static HRESULT FindExeCplClass(LPCWSTR Canonical, HKEY hKey, BOOL Wow64, LPWSTR clsid){ HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); HKEY hNSKey; WCHAR key[MAX_PATH], buf[MAX_PATH]; wsprintfW(key, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\%s\\NameSpace", Wow64 ? L"ControlPanelWOW64" : L"ControlPanel"); LSTATUS error = RegOpenKeyExW(hKey, key, 0, KEY_READ, &hNSKey); if (error) return HRESULT_FROM_WIN32(error); for (DWORD i = 0; RegEnumKeyW(hNSKey, i, key, _countof(key)) == ERROR_SUCCESS; ++i) { IID validate; if (SUCCEEDED(IIDFromString(key, &validate))) { wsprintfW(buf, L"CLSID\\%s", key); DWORD cb = sizeof(buf); if (RegGetValueW(HKEY_CLASSES_ROOT, buf, L"System.ApplicationName", RRF_RT_REG_SZ, NULL, buf, &cb) == ERROR_SUCCESS) { if (!lstrcmpiW(buf, Canonical)) { lstrcpyW(clsid, key); hr = S_OK; } } } } RegCloseKey(hNSKey); return hr;}
static HRESULT FindExeCplClass(LPCWSTR Canonical, LPWSTR clsid){ HRESULT hr = E_FAIL; if (FAILED(hr)) hr = FindExeCplClass(Canonical, HKEY_CURRENT_USER, FALSE, clsid); if (FAILED(hr)) hr = FindExeCplClass(Canonical, HKEY_CURRENT_USER, TRUE, clsid); if (FAILED(hr)) hr = FindExeCplClass(Canonical, HKEY_LOCAL_MACHINE, FALSE, clsid); if (FAILED(hr)) hr = FindExeCplClass(Canonical, HKEY_LOCAL_MACHINE, TRUE, clsid); return hr;}
HRESULT WINAPI COpenControlPanel::Open(LPCWSTR pszName, LPCWSTR pszPage, IUnknown *punkSite){ WCHAR path[MAX_PATH], clspath[MAX_PATH]; HRESULT hr = S_OK; SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_FLAG_DDEWAIT }; sei.lpFile = path; sei.nShow = SW_SHOW; if (!pszName) { GetSystemDirectoryW(path, _countof(path)); PathAppendW(path, L"control.exe"); } else { LPWSTR clsid = clspath + wsprintfW(clspath, L"CLSID\\"); if (SUCCEEDED(hr = FindExeCplClass(pszName, clsid))) { if (SUCCEEDED(hr = CreateCplAbsoluteParsingPath(L"::", clsid, path, _countof(path)))) { // NT6 will execute "::{26EE0668-A00A-44D7-9371-BEB064C98683}\0\::{clsid}[\pszPage]" // but we don't support parsing that so we force the class instead. sei.fMask |= SEE_MASK_CLASSNAME; sei.lpClass = clspath; } } }
if (SUCCEEDED(hr)) { DWORD error = ShellExecuteExW(&sei) ? ERROR_SUCCESS : GetLastError(); hr = HRESULT_FROM_WIN32(error); } return hr;}
HRESULT WINAPI COpenControlPanel::GetPath(LPCWSTR pszName, LPWSTR pszPath, UINT cchPath){ HRESULT hr; if (!pszName) { PWSTR cpfolder; if (SUCCEEDED(hr = GetParsingName((PCIDLIST_ABSOLUTE)CSIDL_CONTROLS, &cpfolder))) { hr = StringCchCopyW(pszPath, cchPath, cpfolder); SHFree(cpfolder); } } else { WCHAR clsid[38 + 1]; if (SUCCEEDED(hr = FindExeCplClass(pszName, clsid))) { hr = CreateCplAbsoluteParsingPath(L"::", clsid, pszPath, cchPath); } } return hr;}
HRESULT WINAPI COpenControlPanel::GetCurrentView(CPVIEW *pView){ *pView = CPVIEW_CLASSIC; return S_OK;}