[SHELL32]
[reactos.git] / dll / win32 / shell32 / folders / CControlPanelFolder.cpp
1 /*
2 * Control panel folder
3 *
4 * Copyright 2003 Martin Fuchs
5 * Copyright 2009 Andrew Hill
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 /*
23 TODO:
24 1. The selected items list should not be stored in CControlPanelFolder, it should
25 be a result returned by an internal method.
26 */
27
28 #include <precomp.h>
29
30 WINE_DEFAULT_DEBUG_CHANNEL(shell);
31
32 /***********************************************************************
33 * control panel implementation in shell namespace
34 */
35
36 class CControlPanelEnum :
37 public CEnumIDListBase
38 {
39 public:
40 CControlPanelEnum();
41 ~CControlPanelEnum();
42 HRESULT WINAPI Initialize(DWORD dwFlags);
43 BOOL RegisterCPanelApp(LPCSTR path);
44 int RegisterRegistryCPanelApps(HKEY hkey_root, LPCSTR szRepPath);
45 int RegisterCPanelFolders(HKEY hkey_root, LPCSTR szRepPath);
46 BOOL CreateCPanelEnumList(DWORD dwFlags);
47
48 BEGIN_COM_MAP(CControlPanelEnum)
49 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
50 END_COM_MAP()
51 };
52
53 /***********************************************************************
54 * IShellFolder [ControlPanel] implementation
55 */
56
57 static const shvheader ControlPanelSFHeader[] = {
58 {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},/*FIXME*/
59 {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 200},/*FIXME*/
60 };
61
62 #define CONROLPANELSHELLVIEWCOLUMNS 2
63
64 CControlPanelEnum::CControlPanelEnum()
65 {
66 }
67
68 CControlPanelEnum::~CControlPanelEnum()
69 {
70 }
71
72 HRESULT WINAPI CControlPanelEnum::Initialize(DWORD dwFlags)
73 {
74 if (CreateCPanelEnumList(dwFlags) == FALSE)
75 return E_FAIL;
76 return S_OK;
77 }
78
79 static LPITEMIDLIST _ILCreateCPanelApplet(LPCSTR pszName, LPCSTR pszDisplayName, LPCSTR pszComment, int iIconIdx)
80 {
81 PIDLCPanelStruct *pCP;
82 LPITEMIDLIST pidl;
83 LPPIDLDATA pData;
84 int cchName, cchDisplayName, cchComment, cbData;
85
86 /* Calculate lengths of given strings */
87 cchName = strlen(pszName);
88 cchDisplayName = strlen(pszDisplayName);
89 cchComment = strlen(pszComment);
90
91 /* Allocate PIDL */
92 cbData = sizeof(pidl->mkid.cb) + sizeof(pData->type) + sizeof(pData->u.cpanel) - sizeof(pData->u.cpanel.szName)
93 + cchName + cchDisplayName + cchComment + 3;
94 pidl = (LPITEMIDLIST)SHAlloc(cbData + sizeof(WORD));
95 if (!pidl)
96 return NULL;
97
98 /* Copy data to allocated memory */
99 pidl->mkid.cb = cbData;
100 pData = (PIDLDATA *)pidl->mkid.abID;
101 pData->type = PT_CPLAPPLET;
102
103 pCP = &pData->u.cpanel;
104 pCP->dummy = 0;
105 pCP->iconIdx = iIconIdx;
106 strcpy(pCP->szName, pszName);
107 pCP->offsDispName = cchName + 1;
108 strcpy(pCP->szName + pCP->offsDispName, pszDisplayName);
109 pCP->offsComment = pCP->offsDispName + cchDisplayName + 1;
110 strcpy(pCP->szName + pCP->offsComment, pszComment);
111
112 /* Add PIDL NULL terminator */
113 *(WORD*)(pCP->szName + pCP->offsComment + cchComment + 1) = 0;
114
115 pcheck(pidl);
116
117 return pidl;
118 }
119
120 /**************************************************************************
121 * _ILGetCPanelPointer()
122 * gets a pointer to the control panel struct stored in the pidl
123 */
124 static PIDLCPanelStruct *_ILGetCPanelPointer(LPCITEMIDLIST pidl)
125 {
126 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
127
128 if (pdata && pdata->type == PT_CPLAPPLET)
129 return (PIDLCPanelStruct *) & (pdata->u.cpanel);
130
131 return NULL;
132 }
133
134 BOOL CControlPanelEnum::RegisterCPanelApp(LPCSTR path)
135 {
136 LPITEMIDLIST pidl;
137 CPlApplet* applet;
138 CPanel panel;
139 CPLINFO info;
140 unsigned i;
141 int iconIdx;
142
143 char displayName[MAX_PATH];
144 char comment[MAX_PATH];
145
146 WCHAR wpath[MAX_PATH];
147
148 MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH);
149
150 panel.first = NULL;
151 applet = Control_LoadApplet(0, wpath, &panel);
152
153 if (applet)
154 {
155 for (i = 0; i < applet->count; ++i)
156 {
157 WideCharToMultiByte(CP_ACP, 0, applet->info[i].szName, -1, displayName, MAX_PATH, 0, 0);
158 WideCharToMultiByte(CP_ACP, 0, applet->info[i].szInfo, -1, comment, MAX_PATH, 0, 0);
159
160 applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info);
161
162 if (info.idIcon > 0)
163 iconIdx = -info.idIcon; /* negative icon index instead of icon number */
164 else
165 iconIdx = 0;
166
167 pidl = _ILCreateCPanelApplet(path, displayName, comment, iconIdx);
168
169 if (pidl)
170 AddToEnumList(pidl);
171 }
172 Control_UnloadApplet(applet);
173 }
174 return TRUE;
175 }
176
177 int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root, LPCSTR szRepPath)
178 {
179 char name[MAX_PATH];
180 char value[MAX_PATH];
181 HKEY hkey;
182
183 int cnt = 0;
184
185 if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
186 {
187 int idx = 0;
188
189 for(; ; idx++)
190 {
191 DWORD nameLen = MAX_PATH;
192 DWORD valueLen = MAX_PATH;
193
194 if (RegEnumValueA(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS)
195 break;
196
197 if (RegisterCPanelApp(value))
198 ++cnt;
199 }
200 RegCloseKey(hkey);
201 }
202
203 return cnt;
204 }
205
206 int CControlPanelEnum::RegisterCPanelFolders(HKEY hkey_root, LPCSTR szRepPath)
207 {
208 char name[MAX_PATH];
209 HKEY hkey;
210
211 int cnt = 0;
212
213 if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
214 {
215 int idx = 0;
216 for (; ; idx++)
217 {
218 if (RegEnumKeyA(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS)
219 break;
220
221 if (*name == '{')
222 {
223 LPITEMIDLIST pidl = _ILCreateGuidFromStrA(name);
224
225 if (pidl && AddToEnumList(pidl))
226 ++cnt;
227 }
228 }
229
230 RegCloseKey(hkey);
231 }
232
233 return cnt;
234 }
235
236 /**************************************************************************
237 * CControlPanelEnum::CreateCPanelEnumList()
238 */
239 BOOL CControlPanelEnum::CreateCPanelEnumList(DWORD dwFlags)
240 {
241 CHAR szPath[MAX_PATH];
242 WIN32_FIND_DATAA wfd;
243 HANDLE hFile;
244
245 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
246
247 /* enumerate control panel folders */
248 if (dwFlags & SHCONTF_FOLDERS)
249 RegisterCPanelFolders(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
250
251 /* enumerate the control panel applets */
252 if (dwFlags & SHCONTF_NONFOLDERS)
253 {
254 LPSTR p;
255
256 GetSystemDirectoryA(szPath, MAX_PATH);
257 p = PathAddBackslashA(szPath);
258 strcpy(p, "*.cpl");
259
260 TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n", this, debugstr_a(szPath));
261 hFile = FindFirstFileA(szPath, &wfd);
262
263 if (hFile != INVALID_HANDLE_VALUE)
264 {
265 do
266 {
267 if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
268 continue;
269
270 if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
271 strcpy(p, wfd.cFileName);
272 if (strcmp(wfd.cFileName, "ncpa.cpl"))
273 RegisterCPanelApp(szPath);
274 }
275 } while(FindNextFileA(hFile, &wfd));
276 FindClose(hFile);
277 }
278
279 RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
280 RegisterRegistryCPanelApps(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
281 }
282 return TRUE;
283 }
284
285 CControlPanelFolder::CControlPanelFolder()
286 {
287 pidlRoot = NULL; /* absolute pidl */
288 dwAttributes = 0; /* attributes returned by GetAttributesOf FIXME: use it */
289 apidl = NULL;
290 cidl = 0;
291 }
292
293 CControlPanelFolder::~CControlPanelFolder()
294 {
295 TRACE("-- destroying IShellFolder(%p)\n", this);
296 SHFree(pidlRoot);
297 }
298
299 HRESULT WINAPI CControlPanelFolder::FinalConstruct()
300 {
301 pidlRoot = _ILCreateControlPanel(); /* my qualified pidl */
302 if (pidlRoot == NULL)
303 return E_OUTOFMEMORY;
304 return S_OK;
305 }
306
307 /**************************************************************************
308 * CControlPanelFolder::ParseDisplayName
309 */
310 HRESULT WINAPI CControlPanelFolder::ParseDisplayName(
311 HWND hwndOwner,
312 LPBC pbc,
313 LPOLESTR lpszDisplayName,
314 DWORD *pchEaten,
315 PIDLIST_RELATIVE *ppidl,
316 DWORD *pdwAttributes)
317 {
318 WCHAR szElement[MAX_PATH];
319 LPCWSTR szNext = NULL;
320 LPITEMIDLIST pidlTemp = NULL;
321 HRESULT hr = S_OK;
322 CLSID clsid;
323
324 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
325 this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
326 pchEaten, ppidl, pdwAttributes);
327
328 if (!lpszDisplayName || !ppidl)
329 return E_INVALIDARG;
330
331 *ppidl = 0;
332
333 if (pchEaten)
334 *pchEaten = 0; /* strange but like the original */
335
336 if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
337 {
338 szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
339 TRACE ("-- element: %s\n", debugstr_w (szElement));
340 CLSIDFromString (szElement + 2, &clsid);
341 pidlTemp = _ILCreateGuid (PT_GUID, clsid);
342 }
343 else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) )
344 {
345 *ppidl = pidlTemp;
346 return S_OK;
347 }
348
349 if (SUCCEEDED(hr) && pidlTemp)
350 {
351 if (szNext && *szNext)
352 {
353 hr = SHELL32_ParseNextElement(this, hwndOwner, pbc,
354 &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
355 }
356 else
357 {
358 if (pdwAttributes && *pdwAttributes)
359 hr = SHELL32_GetItemAttributes(this,
360 pidlTemp, pdwAttributes);
361 }
362 }
363
364 *ppidl = pidlTemp;
365
366 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
367
368 return hr;
369 }
370
371 /**************************************************************************
372 * CControlPanelFolder::EnumObjects
373 */
374 HRESULT WINAPI CControlPanelFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
375 {
376 return ShellObjectCreatorInit<CControlPanelEnum>(dwFlags, IID_IEnumIDList, ppEnumIDList);
377 }
378
379 /**************************************************************************
380 * CControlPanelFolder::BindToObject
381 */
382 HRESULT WINAPI CControlPanelFolder::BindToObject(
383 PCUIDLIST_RELATIVE pidl,
384 LPBC pbcReserved,
385 REFIID riid,
386 LPVOID *ppvOut)
387 {
388 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
389
390 return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
391 }
392
393 /**************************************************************************
394 * CControlPanelFolder::BindToStorage
395 */
396 HRESULT WINAPI CControlPanelFolder::BindToStorage(
397 PCUIDLIST_RELATIVE pidl,
398 LPBC pbcReserved,
399 REFIID riid,
400 LPVOID *ppvOut)
401 {
402 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
403
404 *ppvOut = NULL;
405 return E_NOTIMPL;
406 }
407
408 /**************************************************************************
409 * CControlPanelFolder::CompareIDs
410 */
411
412 HRESULT WINAPI CControlPanelFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
413 {
414 int nReturn;
415
416 TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
417 nReturn = SHELL32_CompareIDs(this, lParam, pidl1, pidl2);
418 TRACE("-- %i\n", nReturn);
419 return nReturn;
420 }
421
422 /**************************************************************************
423 * CControlPanelFolder::CreateViewObject
424 */
425 HRESULT WINAPI CControlPanelFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
426 {
427 CComPtr<IShellView> pShellView;
428 HRESULT hr = E_INVALIDARG;
429
430 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner, shdebugstr_guid(&riid), ppvOut);
431
432 if (ppvOut) {
433 *ppvOut = NULL;
434
435 if (IsEqualIID(riid, IID_IDropTarget)) {
436 WARN("IDropTarget not implemented\n");
437 hr = E_NOTIMPL;
438 } else if (IsEqualIID(riid, IID_IContextMenu)) {
439 WARN("IContextMenu not implemented\n");
440 hr = E_NOTIMPL;
441 } else if (IsEqualIID(riid, IID_IShellView)) {
442 hr = IShellView_Constructor((IShellFolder *)this, &pShellView);
443 if (pShellView) {
444 hr = pShellView->QueryInterface(riid, ppvOut);
445 }
446 }
447 }
448 TRACE("--(%p)->(interface=%p)\n", this, ppvOut);
449 return hr;
450 }
451
452 /**************************************************************************
453 * CControlPanelFolder::GetAttributesOf
454 */
455 HRESULT WINAPI CControlPanelFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
456 {
457 HRESULT hr = S_OK;
458
459 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
460 this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
461
462 if (!rgfInOut)
463 return E_INVALIDARG;
464 if (cidl && !apidl)
465 return E_INVALIDARG;
466
467 if (*rgfInOut == 0)
468 *rgfInOut = ~0;
469
470 while(cidl > 0 && *apidl)
471 {
472 pdump(*apidl);
473 SHELL32_GetItemAttributes(this, *apidl, rgfInOut);
474 apidl++;
475 cidl--;
476 }
477 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
478 *rgfInOut &= ~SFGAO_VALIDATE;
479
480 TRACE("-- result=0x%08x\n", *rgfInOut);
481 return hr;
482 }
483
484 /**************************************************************************
485 * CControlPanelFolder::GetUIObjectOf
486 *
487 * PARAMETERS
488 * HWND hwndOwner, //[in ] Parent window for any output
489 * UINT cidl, //[in ] array size
490 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
491 * REFIID riid, //[in ] Requested Interface
492 * UINT* prgfInOut, //[ ] reserved
493 * LPVOID* ppvObject) //[out] Resulting Interface
494 *
495 */
496 HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner,
497 UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
498 {
499 LPITEMIDLIST pidl;
500 IUnknown *pObj = NULL;
501 HRESULT hr = E_INVALIDARG;
502
503 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
504 this, hwndOwner, cidl, apidl, shdebugstr_guid(&riid), prgfInOut, ppvOut);
505
506 if (ppvOut) {
507 *ppvOut = NULL;
508
509 if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) {
510 // TODO
511 // create a seperate item struct
512 //
513 pObj = (IContextMenu *)this;
514 this->apidl = apidl;
515 this->cidl = cidl;
516 pObj->AddRef();
517 hr = S_OK;
518 } else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) {
519 hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
520 } else if (IsEqualIID(riid, IID_IExtractIconA) && (cidl == 1)) {
521 pidl = ILCombine(pidlRoot, apidl[0]);
522 pObj = IExtractIconA_Constructor(pidl);
523 SHFree(pidl);
524 hr = S_OK;
525 } else if (IsEqualIID(riid, IID_IExtractIconW) && (cidl == 1)) {
526 pidl = ILCombine(pidlRoot, apidl[0]);
527 pObj = IExtractIconW_Constructor(pidl);
528 SHFree(pidl);
529 hr = S_OK;
530 } else if ((IsEqualIID(riid, IID_IShellLinkW) || IsEqualIID(riid, IID_IShellLinkA))
531 && (cidl == 1)) {
532 pidl = ILCombine(pidlRoot, apidl[0]);
533 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
534 SHFree(pidl);
535 } else {
536 hr = E_NOINTERFACE;
537 }
538
539 if (SUCCEEDED(hr) && !pObj)
540 hr = E_OUTOFMEMORY;
541
542 *ppvOut = pObj;
543 }
544 TRACE("(%p)->hr=0x%08x\n", this, hr);
545 return hr;
546 }
547
548 /**************************************************************************
549 * CControlPanelFolder::GetDisplayNameOf
550 */
551 HRESULT WINAPI CControlPanelFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
552 {
553 CHAR szName[MAX_PATH];
554 WCHAR wszName[MAX_PATH+1]; /* +1 for potential backslash */
555 PIDLCPanelStruct *pCPanel;
556 HRESULT hr;
557
558 *szName = '\0';
559
560 TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
561 pdump(pidl);
562
563 if (!pidl)
564 return S_FALSE;
565
566 pCPanel = _ILGetCPanelPointer(pidl);
567
568 if (pCPanel)
569 {
570 /* copy display name from pidl - it was retrived from applet before;
571 SHGDN_FORPARSING does not need special handling */
572 lstrcpyA(szName, pCPanel->szName + pCPanel->offsDispName);
573 }
574 /* take names of special folders only if it's only this folder */
575 else if (_ILIsSpecialFolder(pidl))
576 {
577 BOOL bSimplePidl = _ILIsPidlSimple(pidl);
578 SFGAOF Attr = SFGAO_FILESYSTEM;
579
580 SHELL32_GetItemAttributes(this, pidl, &Attr);
581 if (Attr & SFGAO_FILESYSTEM)
582 {
583 hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, wszName, sizeof(wszName));
584 if (FAILED(hr))
585 return hr;
586 }
587 else if (bSimplePidl)
588 {
589 _ILSimpleGetTextW(pidl, wszName, MAX_PATH); /* append my own path */
590 }
591 else
592 {
593 FIXME("special pidl\n");
594 if (dwFlags & SHGDN_FORPARSING)
595 {
596 /* go deeper if needed */
597 int cchName;
598
599 PathAddBackslashW(wszName);
600 cchName = wcslen(wszName);
601
602 hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, wszName + cchName, MAX_PATH + 1 - cchName);
603 if (FAILED(hr))
604 return hr;
605 }
606 }
607
608 if (!WideCharToMultiByte(CP_ACP, 0, wszName, -1, szName, MAX_PATH, NULL, NULL))
609 szName[0] = '\0';
610 }
611
612 strRet->uType = STRRET_CSTR;
613 lstrcpynA(strRet->cStr, szName, MAX_PATH);
614
615 TRACE("--(%p)->(%s)\n", this, szName);
616 return S_OK;
617 }
618
619 /**************************************************************************
620 * CControlPanelFolder::SetNameOf
621 * Changes the name of a file object or subfolder, possibly changing its item
622 * identifier in the process.
623 *
624 * PARAMETERS
625 * HWND hwndOwner, //[in ] Owner window for output
626 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
627 * LPCOLESTR lpszName, //[in ] the items new display name
628 * DWORD dwFlags, //[in ] SHGNO formatting flags
629 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
630 */
631 HRESULT WINAPI CControlPanelFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /*simple pidl */
632 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
633 {
634 FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut);
635 return E_FAIL;
636 }
637
638 HRESULT WINAPI CControlPanelFolder::GetDefaultSearchGUID(GUID *pguid)
639 {
640 FIXME("(%p)\n", this);
641 return E_NOTIMPL;
642 }
643
644 HRESULT WINAPI CControlPanelFolder::EnumSearches(IEnumExtraSearch **ppenum)
645 {
646 FIXME("(%p)\n", this);
647 return E_NOTIMPL;
648 }
649
650 HRESULT WINAPI CControlPanelFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
651 {
652 TRACE("(%p)\n", this);
653
654 if (pSort) *pSort = 0;
655 if (pDisplay) *pDisplay = 0;
656 return S_OK;
657 }
658
659 HRESULT WINAPI CControlPanelFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
660 {
661 TRACE("(%p)\n", this);
662
663 if (!pcsFlags || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) return E_INVALIDARG;
664 *pcsFlags = ControlPanelSFHeader[iColumn].pcsFlags;
665 return S_OK;
666 }
667
668 HRESULT WINAPI CControlPanelFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
669 {
670 FIXME("(%p)\n", this);
671 return E_NOTIMPL;
672 }
673
674 HRESULT WINAPI CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
675 {
676 HRESULT hr;
677
678 TRACE("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
679
680 if (!psd || iColumn >= CONROLPANELSHELLVIEWCOLUMNS)
681 return E_INVALIDARG;
682
683 if (!pidl) {
684 psd->fmt = ControlPanelSFHeader[iColumn].fmt;
685 psd->cxChar = ControlPanelSFHeader[iColumn].cxChar;
686 psd->str.uType = STRRET_CSTR;
687 LoadStringA(shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid, psd->str.cStr, MAX_PATH);
688 return S_OK;
689 } else {
690 psd->str.cStr[0] = 0x00;
691 psd->str.uType = STRRET_CSTR;
692 switch(iColumn) {
693 case 0: /* name */
694 hr = GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
695 break;
696 case 1: /* comment */
697 _ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
698 break;
699 }
700 hr = S_OK;
701 }
702
703 return hr;
704 }
705
706 HRESULT WINAPI CControlPanelFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
707 {
708 FIXME("(%p)\n", this);
709 return E_NOTIMPL;
710 }
711
712 /************************************************************************
713 * CControlPanelFolder::GetClassID
714 */
715 HRESULT WINAPI CControlPanelFolder::GetClassID(CLSID *lpClassId)
716 {
717 TRACE("(%p)\n", this);
718
719 if (!lpClassId)
720 return E_POINTER;
721 *lpClassId = CLSID_ControlPanel;
722
723 return S_OK;
724 }
725
726 /************************************************************************
727 * CControlPanelFolder::Initialize
728 *
729 * NOTES: it makes no sense to change the pidl
730 */
731 HRESULT WINAPI CControlPanelFolder::Initialize(LPCITEMIDLIST pidl)
732 {
733 if (pidlRoot)
734 SHFree((LPVOID)pidlRoot);
735
736 pidlRoot = ILClone(pidl);
737 return S_OK;
738 }
739
740 /**************************************************************************
741 * CControlPanelFolder::GetCurFolder
742 */
743 HRESULT WINAPI CControlPanelFolder::GetCurFolder(LPITEMIDLIST * pidl)
744 {
745 TRACE("(%p)->(%p)\n", this, pidl);
746
747 if (!pidl)
748 return E_POINTER;
749 *pidl = ILClone(pidlRoot);
750 return S_OK;
751 }
752
753 HRESULT CPanel_GetIconLocationW(LPCITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex)
754 {
755 PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl);
756
757 if (!pcpanel)
758 return E_INVALIDARG;
759
760 MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, szIconFile, cchMax);
761 *piIndex = (int)pcpanel->iconIdx != -1 ? pcpanel->iconIdx : 0;
762
763 return S_OK;
764 }
765
766 /**************************************************************************
767 * IContextMenu2 Implementation
768 */
769
770 /**************************************************************************
771 * ICPanel_IContextMenu_QueryContextMenu()
772 */
773 HRESULT WINAPI CControlPanelFolder::QueryContextMenu(
774 HMENU hMenu,
775 UINT indexMenu,
776 UINT idCmdFirst,
777 UINT idCmdLast,
778 UINT uFlags)
779 {
780 WCHAR szBuffer[30] = {0};
781 ULONG Count = 1;
782
783 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
784 this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
785
786 if (LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
787 {
788 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
789 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_OPEN, MFT_STRING, szBuffer, MFS_DEFAULT); //FIXME identifier
790 Count++;
791 }
792
793 if (LoadStringW(shell32_hInstance, IDS_CREATELINK, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
794 {
795 if (Count)
796 {
797 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_SEPARATOR, NULL, MFS_ENABLED);
798 }
799 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
800
801 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_CREATELINK, MFT_STRING, szBuffer, MFS_ENABLED); //FIXME identifier
802 Count++;
803 }
804 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
805 }
806
807 /**************************************************************************
808 * ICPanel_IContextMenu_InvokeCommand()
809 */
810 HRESULT WINAPI CControlPanelFolder::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
811 {
812 WCHAR szPath[MAX_PATH];
813 char szTarget[MAX_PATH];
814 STRRET strret;
815 WCHAR* pszPath;
816 INT Length, cLength;
817 CComPtr<IPersistFile> ppf;
818 CComPtr<IShellLinkA> isl;
819 HRESULT hResult;
820
821 PIDLCPanelStruct *pcpanel = _ILGetCPanelPointer(apidl[0]);
822
823 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
824
825 if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_OPEN)) //FIXME
826 {
827 LPITEMIDLIST lpIDList = ILCombine(pidlRoot, apidl[0]);
828
829 if (!pcpanel)
830 {
831 /* UGLY HACK! */
832 LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageW(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
833 HRESULT hr;
834
835 if (lpSB == NULL)
836 return E_FAIL;
837
838 hr = lpSB->BrowseObject(lpIDList, 0);
839 return hr;
840 }
841
842 /* Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */
843 ShellExecuteA(NULL, "cplopen", pcpanel->szName, pcpanel->szName + pcpanel->offsDispName, NULL, 0);
844 }
845 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_CREATELINK)) //FIXME
846 {
847 if (!SHGetSpecialFolderPathW(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE))
848 return E_FAIL;
849
850 pszPath = PathAddBackslashW(szPath);
851 if (!pszPath)
852 return E_FAIL;
853
854 if (GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strret) != S_OK)
855 return E_FAIL;
856
857 Length = MAX_PATH - (pszPath - szPath);
858 cLength = strlen(strret.cStr);
859 if (Length < cLength + 5)
860 {
861 FIXME("\n");
862 return E_FAIL;
863 }
864
865 if (MultiByteToWideChar(CP_ACP, 0, strret.cStr, cLength + 1, pszPath, Length))
866 {
867 pszPath += cLength;
868 Length -= cLength;
869 }
870
871 if (Length > 10)
872 {
873 wcscpy(pszPath, L" - ");
874 cLength = LoadStringW(shell32_hInstance, IDS_LNK_FILE, &pszPath[3], Length - 4) + 3;
875 if (cLength + 5 > Length)
876 cLength = Length - 5;
877 Length -= cLength;
878 pszPath += cLength;
879 }
880 wcscpy(pszPath, L".lnk");
881
882 pcpanel = _ILGetCPanelPointer(ILFindLastID(apidl[0]));
883 if (pcpanel)
884 {
885 strncpy(szTarget, pcpanel->szName, MAX_PATH);
886 }
887 else
888 {
889 FIXME("Couldn't retrieve pointer to cpl structure\n");
890 return E_FAIL;
891 }
892 hResult = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkA, &isl));
893 if (SUCCEEDED(hResult))
894 {
895 isl->SetPath(szTarget);
896 if (SUCCEEDED(isl->QueryInterface(IID_PPV_ARG(IPersistFile,&ppf))))
897 ppf->Save(szPath, TRUE);
898 }
899 return NOERROR;
900 }
901 return S_OK;
902 }
903
904 /**************************************************************************
905 * ICPanel_IContextMenu_GetCommandString()
906 *
907 */
908 HRESULT WINAPI CControlPanelFolder::GetCommandString(
909 UINT_PTR idCommand,
910 UINT uFlags,
911 UINT* lpReserved,
912 LPSTR lpszName,
913 UINT uMaxNameLen)
914 {
915 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
916
917 FIXME("unknown command string\n");
918 return E_FAIL;
919 }
920
921 /**************************************************************************
922 * ICPanel_IContextMenu_HandleMenuMsg()
923 */
924 HRESULT WINAPI CControlPanelFolder::HandleMenuMsg(
925 UINT uMsg,
926 WPARAM wParam,
927 LPARAM lParam)
928 {
929 TRACE("ICPanel_IContextMenu_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
930
931 return E_NOTIMPL;
932 }