1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Control panel folder
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2003 Martin Fuchs
5c2c66affSColin Finck  * Copyright 2009 Andrew Hill
6c2c66affSColin Finck  *
7c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
8c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck  * License as published by the Free Software Foundation; either
10c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck  *
12c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
13c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15c2c66affSColin Finck  * Lesser General Public License for more details.
16c2c66affSColin Finck  *
17c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20c2c66affSColin Finck  */
21c2c66affSColin Finck 
22c2c66affSColin Finck #include <precomp.h>
23c2c66affSColin Finck 
24c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(shell);
25c2c66affSColin Finck 
266ae11ba0SWhindmar Saksit static const REGFOLDERINFO g_RegFolderInfo =
276ae11ba0SWhindmar Saksit {
286ae11ba0SWhindmar Saksit     PT_CONTROLS_NEWREGITEM,
296ae11ba0SWhindmar Saksit     0, NULL,
306ae11ba0SWhindmar Saksit     CLSID_ControlPanel,
316ae11ba0SWhindmar Saksit     L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}",
326ae11ba0SWhindmar Saksit     L"ControlPanel",
336ae11ba0SWhindmar Saksit };
346ae11ba0SWhindmar Saksit 
35c2c66affSColin Finck /***********************************************************************
36c2c66affSColin Finck *   control panel implementation in shell namespace
37c2c66affSColin Finck */
38c2c66affSColin Finck 
39c2c66affSColin Finck class CControlPanelEnum :
40c2c66affSColin Finck     public CEnumIDListBase
41c2c66affSColin Finck {
42c2c66affSColin Finck     public:
43c2c66affSColin Finck         CControlPanelEnum();
44c2c66affSColin Finck         ~CControlPanelEnum();
45c2c66affSColin Finck         HRESULT WINAPI Initialize(DWORD dwFlags, IEnumIDList* pRegEnumerator);
46c2c66affSColin Finck         BOOL RegisterCPanelApp(LPCWSTR path);
47c2c66affSColin Finck         int RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath);
48c2c66affSColin Finck         BOOL CreateCPanelEnumList(DWORD dwFlags);
49c2c66affSColin Finck 
50c2c66affSColin Finck         BEGIN_COM_MAP(CControlPanelEnum)
51c2c66affSColin Finck         COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
52c2c66affSColin Finck         END_COM_MAP()
53c2c66affSColin Finck };
54c2c66affSColin Finck 
55c2c66affSColin Finck /***********************************************************************
56c2c66affSColin Finck *   IShellFolder [ControlPanel] implementation
57c2c66affSColin Finck */
58c2c66affSColin Finck 
59c2c66affSColin Finck static const shvheader ControlPanelSFHeader[] = {
60c2c66affSColin Finck     {IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 20},/*FIXME*/
61c2c66affSColin Finck     {IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 80},/*FIXME*/
62c2c66affSColin Finck };
63c2c66affSColin Finck 
644c25af5bSMuthu R Kumar enum controlpanel_columns
654c25af5bSMuthu R Kumar {
664c25af5bSMuthu R Kumar     CONTROLPANEL_COL_NAME,
674c25af5bSMuthu R Kumar     CONTROLPANEL_COL_COMMENT,
684c25af5bSMuthu R Kumar     CONTROLPANEL_COL_COUNT,
694c25af5bSMuthu R Kumar };
70c2c66affSColin Finck 
CControlPanelEnum()71c2c66affSColin Finck CControlPanelEnum::CControlPanelEnum()
72c2c66affSColin Finck {
73c2c66affSColin Finck }
74c2c66affSColin Finck 
~CControlPanelEnum()75c2c66affSColin Finck CControlPanelEnum::~CControlPanelEnum()
76c2c66affSColin Finck {
77c2c66affSColin Finck }
78c2c66affSColin Finck 
Initialize(DWORD dwFlags,IEnumIDList * pRegEnumerator)79c2c66affSColin Finck HRESULT WINAPI CControlPanelEnum::Initialize(DWORD dwFlags, IEnumIDList* pRegEnumerator)
80c2c66affSColin Finck {
81c2c66affSColin Finck     if (CreateCPanelEnumList(dwFlags) == FALSE)
82c2c66affSColin Finck         return E_FAIL;
83c2c66affSColin Finck     AppendItemsFromEnumerator(pRegEnumerator);
84c2c66affSColin Finck     return S_OK;
85c2c66affSColin Finck }
86c2c66affSColin Finck 
_ILCreateCPanelApplet(LPCWSTR pszName,LPCWSTR pszDisplayName,LPCWSTR pszComment,int iIconIdx)87c2c66affSColin Finck static LPITEMIDLIST _ILCreateCPanelApplet(LPCWSTR pszName, LPCWSTR pszDisplayName, LPCWSTR pszComment, int iIconIdx)
88c2c66affSColin Finck {
89c2c66affSColin Finck     PIDLCPanelStruct *pCP;
90c2c66affSColin Finck     LPITEMIDLIST pidl;
91c2c66affSColin Finck     LPPIDLDATA pData;
92c2c66affSColin Finck     int cchName, cchDisplayName, cchComment, cbData;
93c2c66affSColin Finck 
94c2c66affSColin Finck     /* Calculate lengths of given strings */
95c2c66affSColin Finck     cchName = wcslen(pszName);
96c2c66affSColin Finck     cchDisplayName = wcslen(pszDisplayName);
97c2c66affSColin Finck     cchComment = wcslen(pszComment);
98c2c66affSColin Finck 
99c2c66affSColin Finck     /* Allocate PIDL */
100c2c66affSColin Finck     cbData = sizeof(pidl->mkid.cb) + sizeof(pData->type) + sizeof(pData->u.cpanel) - sizeof(pData->u.cpanel.szName)
101c2c66affSColin Finck              + (cchName + cchDisplayName + cchComment + 3) * sizeof(WCHAR);
102c2c66affSColin Finck     pidl = (LPITEMIDLIST)SHAlloc(cbData + sizeof(WORD));
103c2c66affSColin Finck     if (!pidl)
104c2c66affSColin Finck         return NULL;
105c2c66affSColin Finck 
106c2c66affSColin Finck     /* Copy data to allocated memory */
107c2c66affSColin Finck     pidl->mkid.cb = cbData;
108c2c66affSColin Finck     pData = (PIDLDATA *)pidl->mkid.abID;
109c2c66affSColin Finck     pData->type = PT_CPLAPPLET;
110c2c66affSColin Finck 
111c2c66affSColin Finck     pCP = &pData->u.cpanel;
112c2c66affSColin Finck     pCP->dummy = 0;
113c2c66affSColin Finck     pCP->iconIdx = iIconIdx;
114c2c66affSColin Finck     wcscpy(pCP->szName, pszName);
115c2c66affSColin Finck     pCP->offsDispName = cchName + 1;
116c2c66affSColin Finck     wcscpy(pCP->szName + pCP->offsDispName, pszDisplayName);
117c2c66affSColin Finck     pCP->offsComment = pCP->offsDispName + cchDisplayName + 1;
118c2c66affSColin Finck     wcscpy(pCP->szName + pCP->offsComment, pszComment);
119c2c66affSColin Finck 
120c2c66affSColin Finck     /* Add PIDL NULL terminator */
121c2c66affSColin Finck     *(WORD*)(pCP->szName + pCP->offsComment + cchComment + 1) = 0;
122c2c66affSColin Finck 
123c2c66affSColin Finck     pcheck(pidl);
124c2c66affSColin Finck 
125c2c66affSColin Finck     return pidl;
126c2c66affSColin Finck }
127c2c66affSColin Finck 
128c2c66affSColin Finck /**************************************************************************
129c2c66affSColin Finck  *  _ILGetCPanelPointer()
130c2c66affSColin Finck  * gets a pointer to the control panel struct stored in the pidl
131c2c66affSColin Finck  */
_ILGetCPanelPointer(LPCITEMIDLIST pidl)132c2c66affSColin Finck static PIDLCPanelStruct *_ILGetCPanelPointer(LPCITEMIDLIST pidl)
133c2c66affSColin Finck {
134c2c66affSColin Finck     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
135c2c66affSColin Finck 
136c2c66affSColin Finck     if (pdata && pdata->type == PT_CPLAPPLET)
137c2c66affSColin Finck         return (PIDLCPanelStruct *) & (pdata->u.cpanel);
138c2c66affSColin Finck 
139c2c66affSColin Finck     return NULL;
140c2c66affSColin Finck }
141c2c66affSColin Finck 
CCPLExtractIcon_CreateInstance(IShellFolder * psf,LPCITEMIDLIST pidl,REFIID riid,LPVOID * ppvOut)142c2c66affSColin Finck HRESULT CCPLExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
143c2c66affSColin Finck {
144c2c66affSColin Finck     PIDLCPanelStruct *pData = _ILGetCPanelPointer(pidl);
145c2c66affSColin Finck     if (!pData)
146c2c66affSColin Finck         return E_FAIL;
147c2c66affSColin Finck 
148c2c66affSColin Finck     CComPtr<IDefaultExtractIconInit> initIcon;
149c2c66affSColin Finck     HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
150c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
151c2c66affSColin Finck         return hr;
152c2c66affSColin Finck 
153c2c66affSColin Finck     initIcon->SetNormalIcon(pData->szName, (int)pData->iconIdx != -1 ? pData->iconIdx : 0);
154c2c66affSColin Finck 
155c2c66affSColin Finck     return initIcon->QueryInterface(riid, ppvOut);
156c2c66affSColin Finck }
157c2c66affSColin Finck 
RegisterCPanelApp(LPCWSTR wpath)158c2c66affSColin Finck BOOL CControlPanelEnum::RegisterCPanelApp(LPCWSTR wpath)
159c2c66affSColin Finck {
160c2c66affSColin Finck     CPlApplet* applet = Control_LoadApplet(0, wpath, NULL);
161c2c66affSColin Finck     int iconIdx;
162c2c66affSColin Finck 
163c2c66affSColin Finck     if (applet)
164c2c66affSColin Finck     {
165c2c66affSColin Finck         for (UINT i = 0; i < applet->count; ++i)
166c2c66affSColin Finck         {
167c2c66affSColin Finck             if (applet->info[i].idIcon > 0)
168c2c66affSColin Finck                 iconIdx = -applet->info[i].idIcon; /* negative icon index instead of icon number */
169c2c66affSColin Finck             else
170c2c66affSColin Finck                 iconIdx = 0;
171c2c66affSColin Finck 
172c2c66affSColin Finck             LPITEMIDLIST pidl = _ILCreateCPanelApplet(wpath,
173c2c66affSColin Finck                                                       applet->info[i].name,
174c2c66affSColin Finck                                                       applet->info[i].info,
175c2c66affSColin Finck                                                       iconIdx);
176c2c66affSColin Finck 
177c2c66affSColin Finck             if (pidl)
178c2c66affSColin Finck                 AddToEnumList(pidl);
179c2c66affSColin Finck         }
180c2c66affSColin Finck         Control_UnloadApplet(applet);
181c2c66affSColin Finck     }
182c2c66affSColin Finck     return TRUE;
183c2c66affSColin Finck }
184c2c66affSColin Finck 
RegisterRegistryCPanelApps(HKEY hkey_root,LPCWSTR szRepPath)185c2c66affSColin Finck int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath)
186c2c66affSColin Finck {
187c2c66affSColin Finck     WCHAR name[MAX_PATH];
188c2c66affSColin Finck     WCHAR value[MAX_PATH];
189c2c66affSColin Finck     HKEY hkey;
190c2c66affSColin Finck 
191c2c66affSColin Finck     int cnt = 0;
192c2c66affSColin Finck 
193c2c66affSColin Finck     if (RegOpenKeyW(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
194c2c66affSColin Finck     {
195c2c66affSColin Finck         int idx = 0;
196c2c66affSColin Finck 
197c2c66affSColin Finck         for(; ; idx++)
198c2c66affSColin Finck         {
199c2c66affSColin Finck             DWORD nameLen = MAX_PATH;
200c2c66affSColin Finck             DWORD valueLen = MAX_PATH;
201c2c66affSColin Finck             WCHAR buffer[MAX_PATH];
202c2c66affSColin Finck 
203c2c66affSColin Finck             if (RegEnumValueW(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS)
204c2c66affSColin Finck                 break;
205c2c66affSColin Finck 
206c2c66affSColin Finck             if (ExpandEnvironmentStringsW(value, buffer, MAX_PATH))
207c2c66affSColin Finck             {
208c2c66affSColin Finck                 wcscpy(value, buffer);
209c2c66affSColin Finck             }
210c2c66affSColin Finck 
211c2c66affSColin Finck             if (RegisterCPanelApp(value))
212c2c66affSColin Finck                 ++cnt;
213c2c66affSColin Finck         }
214c2c66affSColin Finck         RegCloseKey(hkey);
215c2c66affSColin Finck     }
216c2c66affSColin Finck 
217c2c66affSColin Finck     return cnt;
218c2c66affSColin Finck }
219c2c66affSColin Finck 
220c2c66affSColin Finck /**************************************************************************
221c2c66affSColin Finck  *  CControlPanelEnum::CreateCPanelEnumList()
222c2c66affSColin Finck  */
CreateCPanelEnumList(DWORD dwFlags)223c2c66affSColin Finck BOOL CControlPanelEnum::CreateCPanelEnumList(DWORD dwFlags)
224c2c66affSColin Finck {
225c2c66affSColin Finck     WCHAR szPath[MAX_PATH];
226c2c66affSColin Finck     WIN32_FIND_DATAW wfd;
227c2c66affSColin Finck     HANDLE hFile;
228c2c66affSColin Finck 
229c2c66affSColin Finck     TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
230c2c66affSColin Finck 
231c2c66affSColin Finck     /* enumerate the control panel applets */
232c2c66affSColin Finck     if (dwFlags & SHCONTF_NONFOLDERS)
233c2c66affSColin Finck     {
234c2c66affSColin Finck         LPWSTR p;
235c2c66affSColin Finck 
236c2c66affSColin Finck         GetSystemDirectoryW(szPath, MAX_PATH);
237c2c66affSColin Finck         p = PathAddBackslashW(szPath);
238c2c66affSColin Finck         wcscpy(p, L"*.cpl");
239c2c66affSColin Finck 
240c2c66affSColin Finck         hFile = FindFirstFileW(szPath, &wfd);
241c2c66affSColin Finck 
242c2c66affSColin Finck         if (hFile != INVALID_HANDLE_VALUE)
243c2c66affSColin Finck         {
244c2c66affSColin Finck             do
245c2c66affSColin Finck             {
246c2c66affSColin Finck                 if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
247c2c66affSColin Finck                     continue;
248c2c66affSColin Finck 
249c2c66affSColin Finck                 if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
250c2c66affSColin Finck                     wcscpy(p, wfd.cFileName);
251c2c66affSColin Finck                     if (wcscmp(wfd.cFileName, L"ncpa.cpl"))
252c2c66affSColin Finck                         RegisterCPanelApp(szPath);
253c2c66affSColin Finck                 }
254c2c66affSColin Finck             } while(FindNextFileW(hFile, &wfd));
255c2c66affSColin Finck             FindClose(hFile);
256c2c66affSColin Finck         }
257c2c66affSColin Finck 
258c2c66affSColin Finck         RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
259c2c66affSColin Finck         RegisterRegistryCPanelApps(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
260c2c66affSColin Finck     }
261c2c66affSColin Finck     return TRUE;
262c2c66affSColin Finck }
263c2c66affSColin Finck 
CControlPanelFolder()264c2c66affSColin Finck CControlPanelFolder::CControlPanelFolder()
265c2c66affSColin Finck {
266c2c66affSColin Finck     pidlRoot = NULL;    /* absolute pidl */
267c2c66affSColin Finck }
268c2c66affSColin Finck 
~CControlPanelFolder()269c2c66affSColin Finck CControlPanelFolder::~CControlPanelFolder()
270c2c66affSColin Finck {
271c2c66affSColin Finck     TRACE("-- destroying IShellFolder(%p)\n", this);
272c2c66affSColin Finck     SHFree(pidlRoot);
273c2c66affSColin Finck }
274c2c66affSColin Finck 
275c2c66affSColin Finck /**************************************************************************
276c2c66affSColin Finck *    CControlPanelFolder::ParseDisplayName
277c2c66affSColin Finck */
ParseDisplayName(HWND hwndOwner,LPBC pbc,LPOLESTR lpszDisplayName,DWORD * pchEaten,PIDLIST_RELATIVE * ppidl,DWORD * pdwAttributes)278c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::ParseDisplayName(
279c2c66affSColin Finck     HWND hwndOwner,
280c2c66affSColin Finck     LPBC pbc,
281c2c66affSColin Finck     LPOLESTR lpszDisplayName,
282c2c66affSColin Finck     DWORD *pchEaten,
283c2c66affSColin Finck     PIDLIST_RELATIVE *ppidl,
284c2c66affSColin Finck     DWORD *pdwAttributes)
285c2c66affSColin Finck {
286c2c66affSColin Finck     /* We only support parsing guid names */
287c2c66affSColin Finck     return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
288c2c66affSColin Finck }
289c2c66affSColin Finck 
290c2c66affSColin Finck /**************************************************************************
291c2c66affSColin Finck *        CControlPanelFolder::EnumObjects
292c2c66affSColin Finck */
EnumObjects(HWND hwndOwner,DWORD dwFlags,LPENUMIDLIST * ppEnumIDList)293c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
294c2c66affSColin Finck {
295c2c66affSColin Finck     CComPtr<IEnumIDList> pRegEnumerator;
296c2c66affSColin Finck     m_regFolder->EnumObjects(hwndOwner, dwFlags, &pRegEnumerator);
297c2c66affSColin Finck 
298c2c66affSColin Finck     return ShellObjectCreatorInit<CControlPanelEnum>(dwFlags, pRegEnumerator, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
299c2c66affSColin Finck }
300c2c66affSColin Finck 
301c2c66affSColin Finck /**************************************************************************
302c2c66affSColin Finck *        CControlPanelFolder::BindToObject
303c2c66affSColin Finck */
BindToObject(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)304c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::BindToObject(
305c2c66affSColin Finck     PCUIDLIST_RELATIVE pidl,
306c2c66affSColin Finck     LPBC pbcReserved,
307c2c66affSColin Finck     REFIID riid,
308c2c66affSColin Finck     LPVOID *ppvOut)
309c2c66affSColin Finck {
310c2c66affSColin Finck     return m_regFolder->BindToObject(pidl, pbcReserved, riid, ppvOut);
311c2c66affSColin Finck }
312c2c66affSColin Finck 
313c2c66affSColin Finck /**************************************************************************
314c2c66affSColin Finck *    CControlPanelFolder::BindToStorage
315c2c66affSColin Finck */
BindToStorage(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)316c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::BindToStorage(
317c2c66affSColin Finck     PCUIDLIST_RELATIVE pidl,
318c2c66affSColin Finck     LPBC pbcReserved,
319c2c66affSColin Finck     REFIID riid,
320c2c66affSColin Finck     LPVOID *ppvOut)
321c2c66affSColin Finck {
322c2c66affSColin Finck     FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
323c2c66affSColin Finck 
324c2c66affSColin Finck     *ppvOut = NULL;
325c2c66affSColin Finck     return E_NOTIMPL;
326c2c66affSColin Finck }
327c2c66affSColin Finck 
328c2c66affSColin Finck /**************************************************************************
329c2c66affSColin Finck *     CControlPanelFolder::CompareIDs
330c2c66affSColin Finck */
CompareIDs(LPARAM lParam,PCUIDLIST_RELATIVE pidl1,PCUIDLIST_RELATIVE pidl2)331c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
332c2c66affSColin Finck {
333c2c66affSColin Finck     /* Dont use SHELL32_CompareGuidItems because it would cause guid items to come first */
334c2c66affSColin Finck     if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2))
335c2c66affSColin Finck     {
336c2c66affSColin Finck         return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
337c2c66affSColin Finck     }
338c2c66affSColin Finck     PIDLCPanelStruct *pData1 = _ILGetCPanelPointer(pidl1);
339c2c66affSColin Finck     PIDLCPanelStruct *pData2 = _ILGetCPanelPointer(pidl2);
340c2c66affSColin Finck 
3414c25af5bSMuthu R Kumar     if (!pData1 || !pData2 || LOWORD(lParam) >= CONTROLPANEL_COL_COUNT)
342c2c66affSColin Finck         return E_INVALIDARG;
343c2c66affSColin Finck 
344c2c66affSColin Finck     int result;
345c2c66affSColin Finck     switch(LOWORD(lParam))
346c2c66affSColin Finck     {
3474c25af5bSMuthu R Kumar         case CONTROLPANEL_COL_NAME:
348*e4930be4STimo Kreuzer             result = _wcsicmp(pData1->szName + pData1->offsDispName, pData2->szName + pData2->offsDispName);
349c2c66affSColin Finck             break;
3504c25af5bSMuthu R Kumar         case CONTROLPANEL_COL_COMMENT:
351*e4930be4STimo Kreuzer             result = _wcsicmp(pData1->szName + pData1->offsComment, pData2->szName + pData2->offsComment);
352c2c66affSColin Finck             break;
353c2c66affSColin Finck         default:
354c2c66affSColin Finck             ERR("Got wrong lParam!\n");
355c2c66affSColin Finck             return E_INVALIDARG;
356c2c66affSColin Finck     }
357c2c66affSColin Finck 
358c2c66affSColin Finck     return MAKE_COMPARE_HRESULT(result);
359c2c66affSColin Finck }
360c2c66affSColin Finck 
361c2c66affSColin Finck /**************************************************************************
362c2c66affSColin Finck *    CControlPanelFolder::CreateViewObject
363c2c66affSColin Finck */
CreateViewObject(HWND hwndOwner,REFIID riid,LPVOID * ppvOut)364c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
365c2c66affSColin Finck {
366c2c66affSColin Finck     CComPtr<IShellView>                    pShellView;
367c2c66affSColin Finck     HRESULT hr = E_INVALIDARG;
368c2c66affSColin Finck 
369c2c66affSColin Finck     TRACE("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner, shdebugstr_guid(&riid), ppvOut);
370c2c66affSColin Finck 
371c2c66affSColin Finck     if (ppvOut) {
372c2c66affSColin Finck         *ppvOut = NULL;
373c2c66affSColin Finck 
374c2c66affSColin Finck         if (IsEqualIID(riid, IID_IDropTarget)) {
375c2c66affSColin Finck             WARN("IDropTarget not implemented\n");
376c2c66affSColin Finck             hr = E_NOTIMPL;
377c2c66affSColin Finck         } else if (IsEqualIID(riid, IID_IContextMenu)) {
378c2c66affSColin Finck             WARN("IContextMenu not implemented\n");
379c2c66affSColin Finck             hr = E_NOTIMPL;
380c2c66affSColin Finck         } else if (IsEqualIID(riid, IID_IShellView)) {
381c2c66affSColin Finck             SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this};
382c2c66affSColin Finck             hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
383c2c66affSColin Finck         }
384c2c66affSColin Finck     }
385c2c66affSColin Finck     TRACE("--(%p)->(interface=%p)\n", this, ppvOut);
386c2c66affSColin Finck     return hr;
387c2c66affSColin Finck }
388c2c66affSColin Finck 
389c2c66affSColin Finck /**************************************************************************
390c2c66affSColin Finck *  CControlPanelFolder::GetAttributesOf
391c2c66affSColin Finck */
GetAttributesOf(UINT cidl,PCUITEMID_CHILD_ARRAY apidl,DWORD * rgfInOut)392c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
393c2c66affSColin Finck {
394c2c66affSColin Finck     HRESULT hr = S_OK;
395c2c66affSColin Finck     static const DWORD dwControlPanelAttributes =
396c2c66affSColin Finck         SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK;
397c2c66affSColin Finck 
398c2c66affSColin Finck     TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
399c2c66affSColin Finck           this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
400c2c66affSColin Finck 
401c2c66affSColin Finck     if (!rgfInOut)
402c2c66affSColin Finck         return E_INVALIDARG;
403c2c66affSColin Finck     if (cidl && !apidl)
404c2c66affSColin Finck         return E_INVALIDARG;
405c2c66affSColin Finck 
406c2c66affSColin Finck     if (*rgfInOut == 0)
407c2c66affSColin Finck         *rgfInOut = ~0;
408c2c66affSColin Finck 
409c2c66affSColin Finck     if (!cidl)
410c2c66affSColin Finck     {
411c2c66affSColin Finck         *rgfInOut &= dwControlPanelAttributes;
412c2c66affSColin Finck     }
413c2c66affSColin Finck     else
414c2c66affSColin Finck     {
415c2c66affSColin Finck         while(cidl > 0 && *apidl)
416c2c66affSColin Finck         {
417c2c66affSColin Finck             pdump(*apidl);
418c2c66affSColin Finck             if (_ILIsCPanelStruct(*apidl))
419c2c66affSColin Finck                 *rgfInOut &= SFGAO_CANLINK;
420c2c66affSColin Finck             else if (_ILIsSpecialFolder(*apidl))
421c2c66affSColin Finck                 m_regFolder->GetAttributesOf(1, apidl, rgfInOut);
422c2c66affSColin Finck             else
4236f91b6c0SJoachim Henze                 ERR("Got unknown pidl\n");
424c2c66affSColin Finck             apidl++;
425c2c66affSColin Finck             cidl--;
426c2c66affSColin Finck         }
427c2c66affSColin Finck     }
428c2c66affSColin Finck     /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
429c2c66affSColin Finck     *rgfInOut &= ~SFGAO_VALIDATE;
430c2c66affSColin Finck 
431c2c66affSColin Finck     TRACE("-- result=0x%08x\n", *rgfInOut);
432c2c66affSColin Finck     return hr;
433c2c66affSColin Finck }
434c2c66affSColin Finck 
435c2c66affSColin Finck /**************************************************************************
436c2c66affSColin Finck *    CControlPanelFolder::GetUIObjectOf
437c2c66affSColin Finck *
438c2c66affSColin Finck * PARAMETERS
439c2c66affSColin Finck *  HWND           hwndOwner, //[in ] Parent window for any output
440c2c66affSColin Finck *  UINT           cidl,      //[in ] array size
441c2c66affSColin Finck *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
442c2c66affSColin Finck *  REFIID         riid,      //[in ] Requested Interface
443c2c66affSColin Finck *  UINT*          prgfInOut, //[   ] reserved
444c2c66affSColin Finck *  LPVOID*        ppvObject) //[out] Resulting Interface
445c2c66affSColin Finck *
446c2c66affSColin Finck */
GetUIObjectOf(HWND hwndOwner,UINT cidl,PCUITEMID_CHILD_ARRAY apidl,REFIID riid,UINT * prgfInOut,LPVOID * ppvOut)447c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner,
448c2c66affSColin Finck         UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
449c2c66affSColin Finck {
450c2c66affSColin Finck     LPVOID pObj = NULL;
451c2c66affSColin Finck     HRESULT hr = E_INVALIDARG;
452c2c66affSColin Finck 
453c2c66affSColin Finck     TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
454c2c66affSColin Finck           this, hwndOwner, cidl, apidl, shdebugstr_guid(&riid), prgfInOut, ppvOut);
455c2c66affSColin Finck 
456c2c66affSColin Finck     if (ppvOut) {
457c2c66affSColin Finck         *ppvOut = NULL;
458c2c66affSColin Finck 
459c2c66affSColin Finck         if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) {
460c2c66affSColin Finck             /* HACK: We should use callbacks from CDefaultContextMenu instead of creating one on our own */
461c2c66affSColin Finck             BOOL bHasCpl = FALSE;
462c2c66affSColin Finck             for (UINT i = 0; i < cidl; i++)
463c2c66affSColin Finck             {
464c2c66affSColin Finck                 if(_ILIsCPanelStruct(apidl[i]))
465c2c66affSColin Finck                 {
466c2c66affSColin Finck                     bHasCpl = TRUE;
467c2c66affSColin Finck                 }
468c2c66affSColin Finck             }
469c2c66affSColin Finck 
470c2c66affSColin Finck             if (bHasCpl)
471c2c66affSColin Finck                 hr = ShellObjectCreatorInit<CCPLItemMenu>(cidl, apidl, riid, &pObj);
472c2c66affSColin Finck             else
473c2c66affSColin Finck                 hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
474c2c66affSColin Finck         } else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) {
475c3132711SMark Jansen             hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, TRUE, (IDataObject **)&pObj);
476c2c66affSColin Finck         } else if ((IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && (cidl == 1)) {
477c2c66affSColin Finck             if (_ILGetCPanelPointer(apidl[0]))
478c2c66affSColin Finck                 hr = CCPLExtractIcon_CreateInstance(this, apidl[0], riid, &pObj);
479c2c66affSColin Finck             else
480c2c66affSColin Finck                 hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
481c2c66affSColin Finck         } else {
482c2c66affSColin Finck             hr = E_NOINTERFACE;
483c2c66affSColin Finck         }
484c2c66affSColin Finck 
485c2c66affSColin Finck         if (SUCCEEDED(hr) && !pObj)
486c2c66affSColin Finck             hr = E_OUTOFMEMORY;
487c2c66affSColin Finck 
488c2c66affSColin Finck         *ppvOut = pObj;
489c2c66affSColin Finck     }
490c2c66affSColin Finck     TRACE("(%p)->hr=0x%08x\n", this, hr);
491c2c66affSColin Finck     return hr;
492c2c66affSColin Finck }
493c2c66affSColin Finck 
494c2c66affSColin Finck /**************************************************************************
495c2c66affSColin Finck *    CControlPanelFolder::GetDisplayNameOf
496c2c66affSColin Finck */
GetDisplayNameOf(PCUITEMID_CHILD pidl,DWORD dwFlags,LPSTRRET strRet)497c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
498c2c66affSColin Finck {
499c2c66affSColin Finck     if (!pidl)
500c2c66affSColin Finck         return S_FALSE;
501c2c66affSColin Finck 
502c2c66affSColin Finck     PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(pidl);
503c2c66affSColin Finck 
504c2c66affSColin Finck     if (pCPanel)
505c2c66affSColin Finck     {
506c2c66affSColin Finck         return SHSetStrRet(strRet, pCPanel->szName + pCPanel->offsDispName);
507c2c66affSColin Finck     }
508c2c66affSColin Finck     else if (_ILIsSpecialFolder(pidl))
509c2c66affSColin Finck     {
510c2c66affSColin Finck         return m_regFolder->GetDisplayNameOf(pidl, dwFlags, strRet);
511c2c66affSColin Finck     }
512c2c66affSColin Finck 
513c2c66affSColin Finck     return E_FAIL;
514c2c66affSColin Finck }
515c2c66affSColin Finck 
516c2c66affSColin Finck /**************************************************************************
517c2c66affSColin Finck *  CControlPanelFolder::SetNameOf
518c2c66affSColin Finck *  Changes the name of a file object or subfolder, possibly changing its item
519c2c66affSColin Finck *  identifier in the process.
520c2c66affSColin Finck *
521c2c66affSColin Finck * PARAMETERS
522c2c66affSColin Finck *  HWND          hwndOwner,  //[in ] Owner window for output
523c2c66affSColin Finck *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
524c2c66affSColin Finck *  LPCOLESTR     lpszName,   //[in ] the items new display name
525c2c66affSColin Finck *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
526c2c66affSColin Finck *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
527c2c66affSColin Finck */
SetNameOf(HWND hwndOwner,PCUITEMID_CHILD pidl,LPCOLESTR lpName,DWORD dwFlags,PITEMID_CHILD * pPidlOut)528c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,    /*simple pidl */
529c2c66affSColin Finck         LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
530c2c66affSColin Finck {
531c2c66affSColin Finck     FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut);
532c2c66affSColin Finck     return E_FAIL;
533c2c66affSColin Finck }
534c2c66affSColin Finck 
GetDefaultSearchGUID(GUID * pguid)535c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetDefaultSearchGUID(GUID *pguid)
536c2c66affSColin Finck {
537c2c66affSColin Finck     FIXME("(%p)\n", this);
538c2c66affSColin Finck     return E_NOTIMPL;
539c2c66affSColin Finck }
540c2c66affSColin Finck 
EnumSearches(IEnumExtraSearch ** ppenum)541c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::EnumSearches(IEnumExtraSearch **ppenum)
542c2c66affSColin Finck {
543c2c66affSColin Finck     FIXME("(%p)\n", this);
544c2c66affSColin Finck     return E_NOTIMPL;
545c2c66affSColin Finck }
546c2c66affSColin Finck 
GetDefaultColumn(DWORD dwRes,ULONG * pSort,ULONG * pDisplay)547c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
548c2c66affSColin Finck {
549c2c66affSColin Finck     TRACE("(%p)\n", this);
550c2c66affSColin Finck 
551c2c66affSColin Finck     if (pSort) *pSort = 0;
552c2c66affSColin Finck     if (pDisplay) *pDisplay = 0;
553c2c66affSColin Finck     return S_OK;
554c2c66affSColin Finck }
555c2c66affSColin Finck 
GetDefaultColumnState(UINT iColumn,DWORD * pcsFlags)556c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
557c2c66affSColin Finck {
558c2c66affSColin Finck     TRACE("(%p)\n", this);
559c2c66affSColin Finck 
5604c25af5bSMuthu R Kumar     if (!pcsFlags || iColumn >= CONTROLPANEL_COL_COUNT)
5614c25af5bSMuthu R Kumar         return E_INVALIDARG;
5623693d554SDoug Lyons     *pcsFlags = ControlPanelSFHeader[iColumn].colstate;
563c2c66affSColin Finck     return S_OK;
564c2c66affSColin Finck }
565c2c66affSColin Finck 
GetDetailsEx(PCUITEMID_CHILD pidl,const SHCOLUMNID * pscid,VARIANT * pv)566c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
567c2c66affSColin Finck {
568c2c66affSColin Finck     FIXME("(%p)\n", this);
569c2c66affSColin Finck     return E_NOTIMPL;
570c2c66affSColin Finck }
571c2c66affSColin Finck 
GetDetailsOf(PCUITEMID_CHILD pidl,UINT iColumn,SHELLDETAILS * psd)572c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
573c2c66affSColin Finck {
5744c25af5bSMuthu R Kumar     if (!psd || iColumn >= CONTROLPANEL_COL_COUNT)
575c2c66affSColin Finck         return E_INVALIDARG;
576c2c66affSColin Finck 
577c2c66affSColin Finck     if (!pidl)
578c2c66affSColin Finck     {
579c2c66affSColin Finck         psd->fmt = ControlPanelSFHeader[iColumn].fmt;
580c2c66affSColin Finck         psd->cxChar = ControlPanelSFHeader[iColumn].cxChar;
581c2c66affSColin Finck         return SHSetStrRet(&psd->str, shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid);
582c2c66affSColin Finck     }
583c2c66affSColin Finck     else if (_ILIsSpecialFolder(pidl))
584c2c66affSColin Finck     {
585c2c66affSColin Finck         return m_regFolder->GetDetailsOf(pidl, iColumn, psd);
586c2c66affSColin Finck     }
587c2c66affSColin Finck     else
588c2c66affSColin Finck     {
589c2c66affSColin Finck         PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(pidl);
590c2c66affSColin Finck 
591c2c66affSColin Finck         if (!pCPanel)
592c2c66affSColin Finck             return E_FAIL;
593c2c66affSColin Finck 
594c2c66affSColin Finck         switch(iColumn)
595c2c66affSColin Finck         {
5964c25af5bSMuthu R Kumar             case CONTROLPANEL_COL_NAME:
597c2c66affSColin Finck                 return SHSetStrRet(&psd->str, pCPanel->szName + pCPanel->offsDispName);
5984c25af5bSMuthu R Kumar             case CONTROLPANEL_COL_COMMENT:
599c2c66affSColin Finck                 return SHSetStrRet(&psd->str, pCPanel->szName + pCPanel->offsComment);
600c2c66affSColin Finck         }
601c2c66affSColin Finck     }
602c2c66affSColin Finck 
6034c25af5bSMuthu R Kumar     return E_FAIL;
604c2c66affSColin Finck }
605c2c66affSColin Finck 
MapColumnToSCID(UINT column,SHCOLUMNID * pscid)606c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
607c2c66affSColin Finck {
608c2c66affSColin Finck     FIXME("(%p)\n", this);
609c2c66affSColin Finck     return E_NOTIMPL;
610c2c66affSColin Finck }
611c2c66affSColin Finck 
612c2c66affSColin Finck /************************************************************************
613c2c66affSColin Finck  *    CControlPanelFolder::GetClassID
614c2c66affSColin Finck  */
GetClassID(CLSID * lpClassId)615c2c66affSColin Finck HRESULT WINAPI CControlPanelFolder::GetClassID(CLSID *lpClassId)
616c2c66affSColin Finck {
617c2c66affSColin Finck     TRACE("(%p)\n", this);
618c2c66affSColin Finck 
619c2c66affSColin Finck     if (!lpClassId)
620c2c66affSColin Finck         return E_POINTER;
621c2c66affSColin Finck     *lpClassId = CLSID_ControlPanel;
622c2c66affSColin Finck 
623c2c66affSColin Finck     return S_OK;
624c2c66affSColin Finck }
625c2c66affSColin Finck 
626c2c66affSColin Finck /************************************************************************
627c2c66affSColin Finck  *    CControlPanelFolder::Initialize
628c2c66affSColin Finck  *
629c2c66affSColin Finck  * NOTES: it makes no sense to change the pidl
630c2c66affSColin Finck  */
Initialize(PCIDLIST_ABSOLUTE pidl)631c2b476bdSThomas Faber HRESULT WINAPI CControlPanelFolder::Initialize(PCIDLIST_ABSOLUTE pidl)
632c2c66affSColin Finck {
633c2c66affSColin Finck     if (pidlRoot)
634c2c66affSColin Finck         SHFree((LPVOID)pidlRoot);
635c2c66affSColin Finck 
636c2c66affSColin Finck     pidlRoot = ILClone(pidl);
637c2c66affSColin Finck 
638c2c66affSColin Finck     /* Create the inner reg folder */
6396ae11ba0SWhindmar Saksit     REGFOLDERINITDATA RegInit = { static_cast<IShellFolder*>(this), &g_RegFolderInfo };
640c2c66affSColin Finck     HRESULT hr;
6416ae11ba0SWhindmar Saksit     hr = CRegFolder_CreateInstance(&RegInit,
642c2c66affSColin Finck                                    pidlRoot,
643c2c66affSColin Finck                                    IID_PPV_ARG(IShellFolder2, &m_regFolder));
644c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
645c2c66affSColin Finck         return hr;
646c2c66affSColin Finck 
647c2c66affSColin Finck     return S_OK;
648c2c66affSColin Finck }
649c2c66affSColin Finck 
650c2c66affSColin Finck /**************************************************************************
651c2c66affSColin Finck  *    CControlPanelFolder::GetCurFolder
652c2c66affSColin Finck  */
GetCurFolder(PIDLIST_ABSOLUTE * pidl)653b90c24d6SThomas Faber HRESULT WINAPI CControlPanelFolder::GetCurFolder(PIDLIST_ABSOLUTE * pidl)
654c2c66affSColin Finck {
655c2c66affSColin Finck     TRACE("(%p)->(%p)\n", this, pidl);
656c2c66affSColin Finck 
657c2c66affSColin Finck     if (!pidl)
658c2c66affSColin Finck         return E_POINTER;
659c2c66affSColin Finck     *pidl = ILClone(pidlRoot);
660c2c66affSColin Finck     return S_OK;
661c2c66affSColin Finck }
662c2c66affSColin Finck 
CCPLItemMenu()663c2c66affSColin Finck CCPLItemMenu::CCPLItemMenu()
664c2c66affSColin Finck {
665c2c66affSColin Finck     m_apidl = NULL;
666c2c66affSColin Finck     m_cidl = 0;
667c2c66affSColin Finck }
668c2c66affSColin Finck 
Initialize(UINT cidl,PCUITEMID_CHILD_ARRAY apidl)669c2c66affSColin Finck HRESULT WINAPI CCPLItemMenu::Initialize(UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
670c2c66affSColin Finck {
671c2c66affSColin Finck     m_cidl = cidl;
672c2c66affSColin Finck     m_apidl = _ILCopyaPidl(apidl, m_cidl);
673c2c66affSColin Finck     if (m_cidl && !m_apidl)
674c2c66affSColin Finck         return E_OUTOFMEMORY;
675c2c66affSColin Finck 
676c2c66affSColin Finck     return S_OK;
677c2c66affSColin Finck }
678c2c66affSColin Finck 
~CCPLItemMenu()679c2c66affSColin Finck CCPLItemMenu::~CCPLItemMenu()
680c2c66affSColin Finck {
681c2c66affSColin Finck     _ILFreeaPidl(m_apidl, m_cidl);
682c2c66affSColin Finck }
683c2c66affSColin Finck 
QueryContextMenu(HMENU hMenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)684c2c66affSColin Finck HRESULT WINAPI CCPLItemMenu::QueryContextMenu(
685c2c66affSColin Finck     HMENU hMenu,
686c2c66affSColin Finck     UINT indexMenu,
687c2c66affSColin Finck     UINT idCmdFirst,
688c2c66affSColin Finck     UINT idCmdLast,
689c2c66affSColin Finck     UINT uFlags)
690c2c66affSColin Finck {
69183335d3aSScott Maday     _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst, MFT_STRING, MAKEINTRESOURCEW(IDS_OPEN), MFS_DEFAULT);
69283335d3aSScott Maday     _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDC_STATIC, MFT_SEPARATOR, NULL, MFS_ENABLED);
69383335d3aSScott Maday     _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 1, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED);
694c2c66affSColin Finck 
695c2c66affSColin Finck     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 2);
696c2c66affSColin Finck }
697c2c66affSColin Finck 
698c2c66affSColin Finck EXTERN_C
699c2c66affSColin Finck void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
700c2c66affSColin Finck 
701c2c66affSColin Finck /**************************************************************************
702c2c66affSColin Finck * ICPanel_IContextMenu_InvokeCommand()
703c2c66affSColin Finck */
InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)704c2c66affSColin Finck HRESULT WINAPI CCPLItemMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
705c2c66affSColin Finck {
706c2c66affSColin Finck     HRESULT hResult;
707c2c66affSColin Finck 
708c2c66affSColin Finck     PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(m_apidl[0]);
709c2c66affSColin Finck     if(!pCPanel)
710c2c66affSColin Finck         return E_FAIL;
711c2c66affSColin Finck 
712c2c66affSColin Finck     TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
713c2c66affSColin Finck 
71483335d3aSScott Maday     if (lpcmi->lpVerb == MAKEINTRESOURCEA(0))
715c2c66affSColin Finck     {
716c2c66affSColin Finck         /* Hardcode the command here; Executing a cpl file would be fine but we also need to run things like console.dll */
717c2c66affSColin Finck         WCHAR wszParams[MAX_PATH];
718c2c66affSColin Finck         PCWSTR wszFile = L"rundll32.exe";
719c2c66affSColin Finck         PCWSTR wszFormat = L"shell32.dll,Control_RunDLL %s,%s";
720c2c66affSColin Finck 
721c2c66affSColin Finck         wsprintfW(wszParams, wszFormat, pCPanel->szName, pCPanel->szName + pCPanel->offsDispName);
722c2c66affSColin Finck 
723c2c66affSColin Finck         /* Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */
724c2c66affSColin Finck         ShellExecuteW(NULL, NULL, wszFile, wszParams, NULL, 0);
725c2c66affSColin Finck     }
72683335d3aSScott Maday     else if (lpcmi->lpVerb == MAKEINTRESOURCEA(1)) //FIXME
727c2c66affSColin Finck     {
728c2c66affSColin Finck         CComPtr<IDataObject> pDataObj;
729c2c66affSColin Finck         LPITEMIDLIST pidl = _ILCreateControlPanel();
730c2c66affSColin Finck 
731c2c66affSColin Finck         hResult = SHCreateDataObject(pidl, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
732c2c66affSColin Finck         if (FAILED(hResult))
733c2c66affSColin Finck             return hResult;
734c2c66affSColin Finck 
735c2c66affSColin Finck         SHFree(pidl);
736c2c66affSColin Finck 
737c2c66affSColin Finck         //FIXME: Use SHCreateLinks
738c2c66affSColin Finck         CComPtr<IShellFolder> psf;
739c2c66affSColin Finck         CComPtr<IDropTarget> pDT;
740c2c66affSColin Finck 
741c2c66affSColin Finck         hResult = SHGetDesktopFolder(&psf);
742c2c66affSColin Finck         if (FAILED(hResult))
743c2c66affSColin Finck             return hResult;
744c2c66affSColin Finck 
745c2c66affSColin Finck         hResult = psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pDT));
746c2c66affSColin Finck         if (FAILED(hResult))
747c2c66affSColin Finck             return hResult;
748c2c66affSColin Finck 
749c2c66affSColin Finck         SHSimulateDrop(pDT, pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL);
750c2c66affSColin Finck     }
751c2c66affSColin Finck     return S_OK;
752c2c66affSColin Finck }
753c2c66affSColin Finck 
754c2c66affSColin Finck /**************************************************************************
755c2c66affSColin Finck  *  ICPanel_IContextMenu_GetCommandString()
756c2c66affSColin Finck  *
757c2c66affSColin Finck  */
GetCommandString(UINT_PTR idCommand,UINT uFlags,UINT * lpReserved,LPSTR lpszName,UINT uMaxNameLen)758c2c66affSColin Finck HRESULT WINAPI CCPLItemMenu::GetCommandString(
759c2c66affSColin Finck     UINT_PTR idCommand,
760c2c66affSColin Finck     UINT uFlags,
761c2c66affSColin Finck     UINT* lpReserved,
762c2c66affSColin Finck     LPSTR lpszName,
763c2c66affSColin Finck     UINT uMaxNameLen)
764c2c66affSColin Finck {
765c2c66affSColin Finck     TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
766c2c66affSColin Finck 
767c2c66affSColin Finck     FIXME("unknown command string\n");
768c2c66affSColin Finck     return E_FAIL;
769c2c66affSColin Finck }
770c2c66affSColin Finck 
771c2c66affSColin Finck /**************************************************************************
772c2c66affSColin Finck * ICPanel_IContextMenu_HandleMenuMsg()
773c2c66affSColin Finck */
HandleMenuMsg(UINT uMsg,WPARAM wParam,LPARAM lParam)774c2c66affSColin Finck HRESULT WINAPI CCPLItemMenu::HandleMenuMsg(
775c2c66affSColin Finck     UINT uMsg,
776c2c66affSColin Finck     WPARAM wParam,
777c2c66affSColin Finck     LPARAM lParam)
778c2c66affSColin Finck {
779c2c66affSColin Finck     TRACE("ICPanel_IContextMenu_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
780c2c66affSColin Finck 
781c2c66affSColin Finck     return E_NOTIMPL;
782c2c66affSColin Finck }
783d41dec2eSWhindmar Saksit 
784d41dec2eSWhindmar Saksit /**************************************************************************
785d41dec2eSWhindmar Saksit * COpenControlPanel
786d41dec2eSWhindmar Saksit */
787d41dec2eSWhindmar Saksit 
GetParsingName(PCIDLIST_ABSOLUTE pidl,PWSTR * Name)788d41dec2eSWhindmar Saksit static HRESULT GetParsingName(PCIDLIST_ABSOLUTE pidl, PWSTR*Name)
789d41dec2eSWhindmar Saksit {
790d41dec2eSWhindmar Saksit     PIDLIST_ABSOLUTE pidlFree = NULL;
791d41dec2eSWhindmar Saksit     if (IS_INTRESOURCE(pidl))
792d41dec2eSWhindmar Saksit     {
793d41dec2eSWhindmar Saksit         HRESULT hr = SHGetSpecialFolderLocation(NULL, (UINT)(SIZE_T)pidl, &pidlFree);
794d41dec2eSWhindmar Saksit         if (FAILED(hr))
795d41dec2eSWhindmar Saksit             return hr;
796d41dec2eSWhindmar Saksit         pidl = pidlFree;
797d41dec2eSWhindmar Saksit     }
798d41dec2eSWhindmar Saksit     HRESULT hr = SHGetNameFromIDList(pidl, SIGDN_DESKTOPABSOLUTEPARSING, Name);
799d41dec2eSWhindmar Saksit     ILFree(pidlFree);
800d41dec2eSWhindmar Saksit     return hr;
801d41dec2eSWhindmar Saksit }
802d41dec2eSWhindmar Saksit 
CreateCplAbsoluteParsingPath(LPCWSTR Prefix,LPCWSTR InFolderParse,PWSTR Buf,UINT cchBuf)803d41dec2eSWhindmar Saksit static HRESULT CreateCplAbsoluteParsingPath(LPCWSTR Prefix, LPCWSTR InFolderParse, PWSTR Buf, UINT cchBuf)
804d41dec2eSWhindmar Saksit {
805d41dec2eSWhindmar Saksit     PWSTR cpfolder;
806d41dec2eSWhindmar Saksit     HRESULT hr = GetParsingName((PCIDLIST_ABSOLUTE)CSIDL_CONTROLS, &cpfolder);
807d41dec2eSWhindmar Saksit     if (SUCCEEDED(hr))
808d41dec2eSWhindmar Saksit     {
809d41dec2eSWhindmar Saksit         hr = StringCchPrintfW(Buf, cchBuf, L"%s\\%s%s", cpfolder, Prefix, InFolderParse);
810d41dec2eSWhindmar Saksit         SHFree(cpfolder);
811d41dec2eSWhindmar Saksit     }
812d41dec2eSWhindmar Saksit     return hr;
813d41dec2eSWhindmar Saksit }
814d41dec2eSWhindmar Saksit 
FindExeCplClass(LPCWSTR Canonical,HKEY hKey,BOOL Wow64,LPWSTR clsid)815d41dec2eSWhindmar Saksit static HRESULT FindExeCplClass(LPCWSTR Canonical, HKEY hKey, BOOL Wow64, LPWSTR clsid)
816d41dec2eSWhindmar Saksit {
817d41dec2eSWhindmar Saksit     HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
818d41dec2eSWhindmar Saksit     HKEY hNSKey;
819d41dec2eSWhindmar Saksit     WCHAR key[MAX_PATH], buf[MAX_PATH];
820d41dec2eSWhindmar Saksit     wsprintfW(key, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\%s\\NameSpace",
821d41dec2eSWhindmar Saksit               Wow64 ? L"ControlPanelWOW64" : L"ControlPanel");
822d41dec2eSWhindmar Saksit     LSTATUS error = RegOpenKeyExW(hKey, key, 0, KEY_READ, &hNSKey);
823d41dec2eSWhindmar Saksit     if (error)
824d41dec2eSWhindmar Saksit         return HRESULT_FROM_WIN32(error);
825d41dec2eSWhindmar Saksit     for (DWORD i = 0; RegEnumKeyW(hNSKey, i, key, _countof(key)) == ERROR_SUCCESS; ++i)
826d41dec2eSWhindmar Saksit     {
827d41dec2eSWhindmar Saksit         IID validate;
828d41dec2eSWhindmar Saksit         if (SUCCEEDED(IIDFromString(key, &validate)))
829d41dec2eSWhindmar Saksit         {
830d41dec2eSWhindmar Saksit             wsprintfW(buf, L"CLSID\\%s", key);
831d41dec2eSWhindmar Saksit             DWORD cb = sizeof(buf);
832d41dec2eSWhindmar Saksit             if (RegGetValueW(HKEY_CLASSES_ROOT, buf, L"System.ApplicationName",
833d41dec2eSWhindmar Saksit                              RRF_RT_REG_SZ, NULL, buf, &cb) == ERROR_SUCCESS)
834d41dec2eSWhindmar Saksit             {
835d41dec2eSWhindmar Saksit                 if (!lstrcmpiW(buf, Canonical))
836d41dec2eSWhindmar Saksit                 {
837d41dec2eSWhindmar Saksit                     lstrcpyW(clsid, key);
838d41dec2eSWhindmar Saksit                     hr = S_OK;
839d41dec2eSWhindmar Saksit                 }
840d41dec2eSWhindmar Saksit             }
841d41dec2eSWhindmar Saksit         }
842d41dec2eSWhindmar Saksit     }
843d41dec2eSWhindmar Saksit     RegCloseKey(hNSKey);
844d41dec2eSWhindmar Saksit     return hr;
845d41dec2eSWhindmar Saksit }
846d41dec2eSWhindmar Saksit 
FindExeCplClass(LPCWSTR Canonical,LPWSTR clsid)847d41dec2eSWhindmar Saksit static HRESULT FindExeCplClass(LPCWSTR Canonical, LPWSTR clsid)
848d41dec2eSWhindmar Saksit {
849d41dec2eSWhindmar Saksit     HRESULT hr = E_FAIL;
850d41dec2eSWhindmar Saksit     if (FAILED(hr))
851d41dec2eSWhindmar Saksit         hr = FindExeCplClass(Canonical, HKEY_CURRENT_USER, FALSE, clsid);
852d41dec2eSWhindmar Saksit     if (FAILED(hr))
853d41dec2eSWhindmar Saksit         hr = FindExeCplClass(Canonical, HKEY_CURRENT_USER, TRUE, clsid);
854d41dec2eSWhindmar Saksit     if (FAILED(hr))
855d41dec2eSWhindmar Saksit         hr = FindExeCplClass(Canonical, HKEY_LOCAL_MACHINE, FALSE, clsid);
856d41dec2eSWhindmar Saksit     if (FAILED(hr))
857d41dec2eSWhindmar Saksit         hr = FindExeCplClass(Canonical, HKEY_LOCAL_MACHINE, TRUE, clsid);
858d41dec2eSWhindmar Saksit     return hr;
859d41dec2eSWhindmar Saksit }
860d41dec2eSWhindmar Saksit 
Open(LPCWSTR pszName,LPCWSTR pszPage,IUnknown * punkSite)861d41dec2eSWhindmar Saksit HRESULT WINAPI COpenControlPanel::Open(LPCWSTR pszName, LPCWSTR pszPage, IUnknown *punkSite)
862d41dec2eSWhindmar Saksit {
863d41dec2eSWhindmar Saksit     WCHAR path[MAX_PATH], clspath[MAX_PATH];
864d41dec2eSWhindmar Saksit     HRESULT hr = S_OK;
865d41dec2eSWhindmar Saksit     SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_FLAG_DDEWAIT };
866d41dec2eSWhindmar Saksit     sei.lpFile = path;
867d41dec2eSWhindmar Saksit     sei.nShow = SW_SHOW;
868d41dec2eSWhindmar Saksit     if (!pszName)
869d41dec2eSWhindmar Saksit     {
870d41dec2eSWhindmar Saksit         GetSystemDirectoryW(path, _countof(path));
871d41dec2eSWhindmar Saksit         PathAppendW(path, L"control.exe");
872d41dec2eSWhindmar Saksit     }
873d41dec2eSWhindmar Saksit     else
874d41dec2eSWhindmar Saksit     {
875d41dec2eSWhindmar Saksit         LPWSTR clsid = clspath + wsprintfW(clspath, L"CLSID\\");
876d41dec2eSWhindmar Saksit         if (SUCCEEDED(hr = FindExeCplClass(pszName, clsid)))
877d41dec2eSWhindmar Saksit         {
878d41dec2eSWhindmar Saksit             if (SUCCEEDED(hr = CreateCplAbsoluteParsingPath(L"::", clsid, path, _countof(path))))
879d41dec2eSWhindmar Saksit             {
880d41dec2eSWhindmar Saksit                 // NT6 will execute "::{26EE0668-A00A-44D7-9371-BEB064C98683}\0\::{clsid}[\pszPage]"
881d41dec2eSWhindmar Saksit                 // but we don't support parsing that so we force the class instead.
882d41dec2eSWhindmar Saksit                 sei.fMask |= SEE_MASK_CLASSNAME;
883d41dec2eSWhindmar Saksit                 sei.lpClass = clspath;
884d41dec2eSWhindmar Saksit             }
885d41dec2eSWhindmar Saksit         }
886d41dec2eSWhindmar Saksit     }
887d41dec2eSWhindmar Saksit 
888d41dec2eSWhindmar Saksit     if (SUCCEEDED(hr))
889d41dec2eSWhindmar Saksit     {
890d41dec2eSWhindmar Saksit         DWORD error = ShellExecuteExW(&sei) ? ERROR_SUCCESS : GetLastError();
891d41dec2eSWhindmar Saksit         hr = HRESULT_FROM_WIN32(error);
892d41dec2eSWhindmar Saksit     }
893d41dec2eSWhindmar Saksit     return hr;
894d41dec2eSWhindmar Saksit }
895d41dec2eSWhindmar Saksit 
GetPath(LPCWSTR pszName,LPWSTR pszPath,UINT cchPath)896d41dec2eSWhindmar Saksit HRESULT WINAPI COpenControlPanel::GetPath(LPCWSTR pszName, LPWSTR pszPath, UINT cchPath)
897d41dec2eSWhindmar Saksit {
898d41dec2eSWhindmar Saksit     HRESULT hr;
899d41dec2eSWhindmar Saksit     if (!pszName)
900d41dec2eSWhindmar Saksit     {
901d41dec2eSWhindmar Saksit         PWSTR cpfolder;
902d41dec2eSWhindmar Saksit         if (SUCCEEDED(hr = GetParsingName((PCIDLIST_ABSOLUTE)CSIDL_CONTROLS, &cpfolder)))
903d41dec2eSWhindmar Saksit         {
904d41dec2eSWhindmar Saksit             hr = StringCchCopyW(pszPath, cchPath, cpfolder);
905d41dec2eSWhindmar Saksit             SHFree(cpfolder);
906d41dec2eSWhindmar Saksit         }
907d41dec2eSWhindmar Saksit     }
908d41dec2eSWhindmar Saksit     else
909d41dec2eSWhindmar Saksit     {
910d41dec2eSWhindmar Saksit         WCHAR clsid[38 + 1];
911d41dec2eSWhindmar Saksit         if (SUCCEEDED(hr = FindExeCplClass(pszName, clsid)))
912d41dec2eSWhindmar Saksit         {
913d41dec2eSWhindmar Saksit             hr = CreateCplAbsoluteParsingPath(L"::", clsid, pszPath, cchPath);
914d41dec2eSWhindmar Saksit         }
915d41dec2eSWhindmar Saksit     }
916d41dec2eSWhindmar Saksit     return hr;
917d41dec2eSWhindmar Saksit }
918d41dec2eSWhindmar Saksit 
GetCurrentView(CPVIEW * pView)919d41dec2eSWhindmar Saksit HRESULT WINAPI COpenControlPanel::GetCurrentView(CPVIEW *pView)
920d41dec2eSWhindmar Saksit {
921d41dec2eSWhindmar Saksit     *pView = CPVIEW_CLASSIC;
922d41dec2eSWhindmar Saksit     return S_OK;
923d41dec2eSWhindmar Saksit }
924