4 * Copyright 2003 Martin Fuchs
5 * Copyright 2009 Andrew Hill
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.
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.
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
24 1. The selected items list should not be stored in CControlPanelFolder, it should
25 be a result returned by an internal method.
30 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
32 /***********************************************************************
33 * control panel implementation in shell namespace
36 class CControlPanelEnum
:
37 public IEnumIDListImpl
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
);
48 BEGIN_COM_MAP(CControlPanelEnum
)
49 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
53 /***********************************************************************
54 * IShellFolder [ControlPanel] implementation
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*/
62 #define CONROLPANELSHELLVIEWCOLUMNS 2
64 CControlPanelEnum::CControlPanelEnum()
68 CControlPanelEnum::~CControlPanelEnum()
72 HRESULT WINAPI
CControlPanelEnum::Initialize(DWORD dwFlags
)
74 if (CreateCPanelEnumList(dwFlags
) == FALSE
)
79 static LPITEMIDLIST
_ILCreateCPanelApplet(LPCSTR pszName
, LPCSTR pszDisplayName
, LPCSTR pszComment
, int iIconIdx
)
81 PIDLCPanelStruct
*pCP
;
84 int cchName
, cchDisplayName
, cchComment
, cbData
;
86 /* Calculate lengths of given strings */
87 cchName
= strlen(pszName
);
88 cchDisplayName
= strlen(pszDisplayName
);
89 cchComment
= strlen(pszComment
);
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
));
98 /* Copy data to allocated memory */
99 pidl
->mkid
.cb
= cbData
;
100 pData
= (PIDLDATA
*)pidl
->mkid
.abID
;
101 pData
->type
= PT_CPLAPPLET
;
103 pCP
= &pData
->u
.cpanel
;
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
);
112 /* Add PIDL NULL terminator */
113 *(WORD
*)(pCP
->szName
+ pCP
->offsComment
+ cchComment
+ 1) = 0;
120 /**************************************************************************
121 * _ILGetCPanelPointer()
122 * gets a pointer to the control panel struct stored in the pidl
124 static PIDLCPanelStruct
*_ILGetCPanelPointer(LPCITEMIDLIST pidl
)
126 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
128 if (pdata
&& pdata
->type
== PT_CPLAPPLET
)
129 return (PIDLCPanelStruct
*) & (pdata
->u
.cpanel
);
134 BOOL
CControlPanelEnum::RegisterCPanelApp(LPCSTR path
)
143 char displayName
[MAX_PATH
];
144 char comment
[MAX_PATH
];
146 WCHAR wpath
[MAX_PATH
];
148 MultiByteToWideChar(CP_ACP
, 0, path
, -1, wpath
, MAX_PATH
);
151 applet
= Control_LoadApplet(0, wpath
, &panel
);
155 for (i
= 0; i
< applet
->count
; ++i
)
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);
160 applet
->proc(0, CPL_INQUIRE
, i
, (LPARAM
)&info
);
163 iconIdx
= -info
.idIcon
; /* negative icon index instead of icon number */
167 pidl
= _ILCreateCPanelApplet(path
, displayName
, comment
, iconIdx
);
172 Control_UnloadApplet(applet
);
177 int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root
, LPCSTR szRepPath
)
180 char value
[MAX_PATH
];
185 if (RegOpenKeyA(hkey_root
, szRepPath
, &hkey
) == ERROR_SUCCESS
)
191 DWORD nameLen
= MAX_PATH
;
192 DWORD valueLen
= MAX_PATH
;
194 if (RegEnumValueA(hkey
, idx
, name
, &nameLen
, NULL
, NULL
, (LPBYTE
)&value
, &valueLen
) != ERROR_SUCCESS
)
197 if (RegisterCPanelApp(value
))
206 int CControlPanelEnum::RegisterCPanelFolders(HKEY hkey_root
, LPCSTR szRepPath
)
213 if (RegOpenKeyA(hkey_root
, szRepPath
, &hkey
) == ERROR_SUCCESS
)
218 if (RegEnumKeyA(hkey
, idx
, name
, MAX_PATH
) != ERROR_SUCCESS
)
223 LPITEMIDLIST pidl
= _ILCreateGuidFromStrA(name
);
225 if (pidl
&& AddToEnumList(pidl
))
236 /**************************************************************************
237 * CControlPanelEnum::CreateCPanelEnumList()
239 BOOL
CControlPanelEnum::CreateCPanelEnumList(DWORD dwFlags
)
241 CHAR szPath
[MAX_PATH
];
242 WIN32_FIND_DATAA wfd
;
245 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
247 /* enumerate control panel folders */
248 if (dwFlags
& SHCONTF_FOLDERS
)
249 RegisterCPanelFolders(HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
251 /* enumerate the control panel applets */
252 if (dwFlags
& SHCONTF_NONFOLDERS
)
256 GetSystemDirectoryA(szPath
, MAX_PATH
);
257 p
= PathAddBackslashA(szPath
);
260 TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n", this, debugstr_a(szPath
));
261 hFile
= FindFirstFileA(szPath
, &wfd
);
263 if (hFile
!= INVALID_HANDLE_VALUE
)
267 if (!(dwFlags
& SHCONTF_INCLUDEHIDDEN
) && (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
))
270 if (!(wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)) {
271 strcpy(p
, wfd
.cFileName
);
272 if (strcmp(wfd
.cFileName
, "ncpa.cpl"))
273 RegisterCPanelApp(szPath
);
275 } while(FindNextFileA(hFile
, &wfd
));
279 RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
280 RegisterRegistryCPanelApps(HKEY_CURRENT_USER
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
285 CControlPanelFolder::CControlPanelFolder()
287 pidlRoot
= NULL
; /* absolute pidl */
288 dwAttributes
= 0; /* attributes returned by GetAttributesOf FIXME: use it */
293 CControlPanelFolder::~CControlPanelFolder()
295 TRACE("-- destroying IShellFolder(%p)\n", this);
299 HRESULT WINAPI
CControlPanelFolder::FinalConstruct()
301 pidlRoot
= _ILCreateControlPanel(); /* my qualified pidl */
302 if (pidlRoot
== NULL
)
303 return E_OUTOFMEMORY
;
307 /**************************************************************************
308 * CControlPanelFolder::ParseDisplayName
310 HRESULT WINAPI
CControlPanelFolder::ParseDisplayName(
313 LPOLESTR lpszDisplayName
,
316 DWORD
*pdwAttributes
)
318 WCHAR szElement
[MAX_PATH
];
319 LPCWSTR szNext
= NULL
;
320 LPITEMIDLIST pidlTemp
= NULL
;
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
);
328 if (!lpszDisplayName
|| !ppidl
)
334 *pchEaten
= 0; /* strange but like the original */
336 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
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
);
343 else if( (pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, lpszDisplayName
)) )
349 if (SUCCEEDED(hr
) && pidlTemp
)
351 if (szNext
&& *szNext
)
353 hr
= SHELL32_ParseNextElement(this, hwndOwner
, pbc
,
354 &pidlTemp
, (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
358 if (pdwAttributes
&& *pdwAttributes
)
359 hr
= SHELL32_GetItemAttributes(this,
360 pidlTemp
, pdwAttributes
);
366 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
371 /**************************************************************************
372 * CControlPanelFolder::EnumObjects
374 HRESULT WINAPI
CControlPanelFolder::EnumObjects(
377 LPENUMIDLIST
*ppEnumIDList
)
379 CComObject
<CControlPanelEnum
> *theEnumerator
;
380 CComPtr
<IEnumIDList
> result
;
383 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner
, dwFlags
, ppEnumIDList
);
385 if (ppEnumIDList
== NULL
)
387 *ppEnumIDList
= NULL
;
388 ATLTRY (theEnumerator
= new CComObject
<CControlPanelEnum
>);
389 if (theEnumerator
== NULL
)
390 return E_OUTOFMEMORY
;
391 hResult
= theEnumerator
->QueryInterface(IID_PPV_ARG(IEnumIDList
, &result
));
392 if (FAILED (hResult
))
394 delete theEnumerator
;
397 hResult
= theEnumerator
->Initialize (dwFlags
);
398 if (FAILED (hResult
))
400 *ppEnumIDList
= result
.Detach ();
402 TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList
);
407 /**************************************************************************
408 * CControlPanelFolder::BindToObject
410 HRESULT WINAPI
CControlPanelFolder::BindToObject(
416 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
418 return SHELL32_BindToChild(pidlRoot
, NULL
, pidl
, riid
, ppvOut
);
421 /**************************************************************************
422 * CControlPanelFolder::BindToStorage
424 HRESULT WINAPI
CControlPanelFolder::BindToStorage(
430 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
436 /**************************************************************************
437 * CControlPanelFolder::CompareIDs
440 HRESULT WINAPI
CControlPanelFolder::CompareIDs(LPARAM lParam
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
444 TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam
, pidl1
, pidl2
);
445 nReturn
= SHELL32_CompareIDs(this, lParam
, pidl1
, pidl2
);
446 TRACE("-- %i\n", nReturn
);
450 /**************************************************************************
451 * CControlPanelFolder::CreateViewObject
453 HRESULT WINAPI
CControlPanelFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
455 CComPtr
<IShellView
> pShellView
;
456 HRESULT hr
= E_INVALIDARG
;
458 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner
, shdebugstr_guid(&riid
), ppvOut
);
463 if (IsEqualIID(riid
, IID_IDropTarget
)) {
464 WARN("IDropTarget not implemented\n");
466 } else if (IsEqualIID(riid
, IID_IContextMenu
)) {
467 WARN("IContextMenu not implemented\n");
469 } else if (IsEqualIID(riid
, IID_IShellView
)) {
470 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
472 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
476 TRACE("--(%p)->(interface=%p)\n", this, ppvOut
);
480 /**************************************************************************
481 * CControlPanelFolder::GetAttributesOf
483 HRESULT WINAPI
CControlPanelFolder::GetAttributesOf(UINT cidl
, LPCITEMIDLIST
* apidl
, DWORD
* rgfInOut
)
487 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
488 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
498 while(cidl
> 0 && *apidl
)
501 SHELL32_GetItemAttributes(this, *apidl
, rgfInOut
);
505 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
506 *rgfInOut
&= ~SFGAO_VALIDATE
;
508 TRACE("-- result=0x%08x\n", *rgfInOut
);
512 /**************************************************************************
513 * CControlPanelFolder::GetUIObjectOf
516 * HWND hwndOwner, //[in ] Parent window for any output
517 * UINT cidl, //[in ] array size
518 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
519 * REFIID riid, //[in ] Requested Interface
520 * UINT* prgfInOut, //[ ] reserved
521 * LPVOID* ppvObject) //[out] Resulting Interface
524 HRESULT WINAPI
CControlPanelFolder::GetUIObjectOf(HWND hwndOwner
,
525 UINT cidl
, LPCITEMIDLIST
* apidl
, REFIID riid
, UINT
* prgfInOut
, LPVOID
* ppvOut
)
528 IUnknown
*pObj
= NULL
;
529 HRESULT hr
= E_INVALIDARG
;
531 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
532 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid(&riid
), prgfInOut
, ppvOut
);
537 if (IsEqualIID(riid
, IID_IContextMenu
) && (cidl
>= 1)) {
539 // create a seperate item struct
541 pObj
= (IContextMenu
*)this;
546 } else if (IsEqualIID(riid
, IID_IDataObject
) && (cidl
>= 1)) {
547 hr
= IDataObject_Constructor(hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
548 } else if (IsEqualIID(riid
, IID_IExtractIconA
) && (cidl
== 1)) {
549 pidl
= ILCombine(pidlRoot
, apidl
[0]);
550 pObj
= (LPUNKNOWN
) IExtractIconA_Constructor(pidl
);
553 } else if (IsEqualIID(riid
, IID_IExtractIconW
) && (cidl
== 1)) {
554 pidl
= ILCombine(pidlRoot
, apidl
[0]);
555 pObj
= (LPUNKNOWN
) IExtractIconW_Constructor(pidl
);
558 } else if ((IsEqualIID(riid
, IID_IShellLinkW
) || IsEqualIID(riid
, IID_IShellLinkA
))
560 pidl
= ILCombine(pidlRoot
, apidl
[0]);
561 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
567 if (SUCCEEDED(hr
) && !pObj
)
572 TRACE("(%p)->hr=0x%08x\n", this, hr
);
576 /**************************************************************************
577 * CControlPanelFolder::GetDisplayNameOf
579 HRESULT WINAPI
CControlPanelFolder::GetDisplayNameOf(LPCITEMIDLIST pidl
, DWORD dwFlags
, LPSTRRET strRet
)
581 CHAR szName
[MAX_PATH
];
582 WCHAR wszName
[MAX_PATH
+1]; /* +1 for potential backslash */
583 PIDLCPanelStruct
*pCPanel
;
588 TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
594 pCPanel
= _ILGetCPanelPointer(pidl
);
598 /* copy display name from pidl - it was retrived from applet before;
599 SHGDN_FORPARSING does not need special handling */
600 lstrcpyA(szName
, pCPanel
->szName
+ pCPanel
->offsDispName
);
602 /* take names of special folders only if it's only this folder */
603 else if (_ILIsSpecialFolder(pidl
))
605 BOOL bSimplePidl
= _ILIsPidlSimple(pidl
);
606 SFGAOF Attr
= SFGAO_FILESYSTEM
;
608 SHELL32_GetItemAttributes(this, pidl
, &Attr
);
609 if (Attr
& SFGAO_FILESYSTEM
)
611 hr
= SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, wszName
, sizeof(wszName
));
615 else if (bSimplePidl
)
617 _ILSimpleGetTextW(pidl
, wszName
, MAX_PATH
); /* append my own path */
621 FIXME("special pidl\n");
622 if (dwFlags
& SHGDN_FORPARSING
)
624 /* go deeper if needed */
627 PathAddBackslashW(wszName
);
628 cchName
= wcslen(wszName
);
630 hr
= SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, wszName
+ cchName
, MAX_PATH
+ 1 - cchName
);
636 if (!WideCharToMultiByte(CP_ACP
, 0, wszName
, -1, szName
, MAX_PATH
, NULL
, NULL
))
640 strRet
->uType
= STRRET_CSTR
;
641 lstrcpynA(strRet
->cStr
, szName
, MAX_PATH
);
643 TRACE("--(%p)->(%s)\n", this, szName
);
647 /**************************************************************************
648 * CControlPanelFolder::SetNameOf
649 * Changes the name of a file object or subfolder, possibly changing its item
650 * identifier in the process.
653 * HWND hwndOwner, //[in ] Owner window for output
654 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
655 * LPCOLESTR lpszName, //[in ] the items new display name
656 * DWORD dwFlags, //[in ] SHGNO formatting flags
657 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
659 HRESULT WINAPI
CControlPanelFolder::SetNameOf(HWND hwndOwner
, LPCITEMIDLIST pidl
, /*simple pidl */
660 LPCOLESTR lpName
, DWORD dwFlags
, LPITEMIDLIST
* pPidlOut
)
662 FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
, debugstr_w(lpName
), dwFlags
, pPidlOut
);
666 HRESULT WINAPI
CControlPanelFolder::GetDefaultSearchGUID(GUID
*pguid
)
668 FIXME("(%p)\n", this);
672 HRESULT WINAPI
CControlPanelFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
674 FIXME("(%p)\n", this);
678 HRESULT WINAPI
CControlPanelFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
680 TRACE("(%p)\n", this);
682 if (pSort
) *pSort
= 0;
683 if (pDisplay
) *pDisplay
= 0;
687 HRESULT WINAPI
CControlPanelFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
689 TRACE("(%p)\n", this);
691 if (!pcsFlags
|| iColumn
>= CONROLPANELSHELLVIEWCOLUMNS
) return E_INVALIDARG
;
692 *pcsFlags
= ControlPanelSFHeader
[iColumn
].pcsFlags
;
696 HRESULT WINAPI
CControlPanelFolder::GetDetailsEx(LPCITEMIDLIST pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
698 FIXME("(%p)\n", this);
702 HRESULT WINAPI
CControlPanelFolder::GetDetailsOf(LPCITEMIDLIST pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
706 TRACE("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
708 if (!psd
|| iColumn
>= CONROLPANELSHELLVIEWCOLUMNS
)
712 psd
->fmt
= ControlPanelSFHeader
[iColumn
].fmt
;
713 psd
->cxChar
= ControlPanelSFHeader
[iColumn
].cxChar
;
714 psd
->str
.uType
= STRRET_CSTR
;
715 LoadStringA(shell32_hInstance
, ControlPanelSFHeader
[iColumn
].colnameid
, psd
->str
.cStr
, MAX_PATH
);
718 psd
->str
.cStr
[0] = 0x00;
719 psd
->str
.uType
= STRRET_CSTR
;
722 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
724 case 1: /* comment */
725 _ILGetFileType(pidl
, psd
->str
.cStr
, MAX_PATH
);
734 HRESULT WINAPI
CControlPanelFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
736 FIXME("(%p)\n", this);
740 /************************************************************************
741 * CControlPanelFolder::GetClassID
743 HRESULT WINAPI
CControlPanelFolder::GetClassID(CLSID
*lpClassId
)
745 TRACE("(%p)\n", this);
749 *lpClassId
= CLSID_ControlPanel
;
754 /************************************************************************
755 * CControlPanelFolder::Initialize
757 * NOTES: it makes no sense to change the pidl
759 HRESULT WINAPI
CControlPanelFolder::Initialize(LPCITEMIDLIST pidl
)
762 SHFree((LPVOID
)pidlRoot
);
764 pidlRoot
= ILClone(pidl
);
768 /**************************************************************************
769 * CControlPanelFolder::GetCurFolder
771 HRESULT WINAPI
CControlPanelFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
773 TRACE("(%p)->(%p)\n", this, pidl
);
777 *pidl
= ILClone(pidlRoot
);
781 HRESULT
CPanel_GetIconLocationW(LPCITEMIDLIST pidl
, LPWSTR szIconFile
, UINT cchMax
, int* piIndex
)
783 PIDLCPanelStruct
* pcpanel
= _ILGetCPanelPointer(pidl
);
788 MultiByteToWideChar(CP_ACP
, 0, pcpanel
->szName
, -1, szIconFile
, cchMax
);
789 *piIndex
= (int)pcpanel
->iconIdx
!= -1 ? pcpanel
->iconIdx
: 0;
795 /**************************************************************************
796 * IShellExecuteHookW Implementation
800 ExecuteAppletFromCLSID(LPOLESTR pOleStr
)
802 WCHAR wszBuf
[128], wszCmd
[MAX_PATH
];
803 DWORD cbCmd
= sizeof(wszCmd
);
805 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"CLSID\\%s\\shell\\open\\command", pOleStr
);
807 if (RegGetValueW(HKEY_CLASSES_ROOT
, wszBuf
, NULL
, RRF_RT_REG_SZ
, NULL
, (PVOID
)wszCmd
, &cbCmd
) != ERROR_SUCCESS
)
809 ERR("RegGetValueW(%ls) failed with %u\n", wszBuf
, GetLastError());
813 if (!ExpandEnvironmentStringsW(wszCmd
, wszBuf
, _countof(wszBuf
)))
816 PROCESS_INFORMATION pi
;
818 ZeroMemory(&si
, sizeof(si
));
820 if (!CreateProcessW(NULL
, wszBuf
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
823 CloseHandle(pi
.hProcess
);
824 CloseHandle(pi
.hThread
);
828 EXTERN_C
void WINAPI
Control_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
);
830 HRESULT WINAPI
CControlPanelFolder::ExecuteFromIdList(LPCITEMIDLIST pidl
)
832 PIDLCPanelStruct
*pCPanel
= _ILGetCPanelPointer(ILFindLastID(pidl
));
836 /* Is it GUID to control panel applet? */
837 IID
*piid
= _ILGetGUIDPointer(ILFindLastID(pidl
));
843 if (StringFromCLSID(*piid
, &pOleStr
) == S_OK
)
845 HRESULT hr
= ExecuteAppletFromCLSID(pOleStr
);
846 CoTaskMemFree(pOleStr
);
850 ERR("Cannot open cpanel applet\n");
854 /* Build control panel applet cmd
855 Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */
856 WCHAR wszCmd
[2*MAX_PATH
];
857 WCHAR wszAppletName
[MAX_PATH
];
859 if(!MultiByteToWideChar(CP_ACP
, 0, pCPanel
->szName
+ pCPanel
->offsDispName
, -1, wszAppletName
, MAX_PATH
))
862 StringCbPrintfW(wszCmd
, sizeof(wszCmd
), L
"rundll32 shell32.dll,Control_RunDLL \"%hs\",\"%ls\"", pCPanel
->szName
, wszAppletName
);
864 /* Start the applet */
865 TRACE("Run cpl %ls\n", wszCmd
);
867 PROCESS_INFORMATION pi
;
868 ZeroMemory(&si
, sizeof(si
));
870 if (!CreateProcessW(NULL
, wszCmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
873 CloseHandle(pi
.hProcess
);
874 CloseHandle(pi
.hThread
);
878 HRESULT WINAPI
CControlPanelFolder::Execute(LPSHELLEXECUTEINFOW psei
)
880 TRACE("(%p)->execute(%p)\n", this, psei
);
885 if (!(psei
->fMask
& SEE_MASK_IDLIST
))
887 FIXME("no idlist given!\n");
891 return ExecuteFromIdList((LPCITEMIDLIST
)psei
->lpIDList
);
894 /**************************************************************************
895 * IShellExecuteHookA Implementation
898 HRESULT WINAPI
CControlPanelFolder::Execute(LPSHELLEXECUTEINFOA psei
)
900 TRACE("(%p)->execute(%p)\n", this, psei
);
905 if (!(psei
->fMask
& SEE_MASK_IDLIST
))
907 FIXME("no idlist given!\n");
911 return ExecuteFromIdList((LPCITEMIDLIST
)psei
->lpIDList
);
914 /**************************************************************************
915 * IContextMenu2 Implementation
918 /**************************************************************************
919 * ICPanel_IContextMenu_QueryContextMenu()
921 HRESULT WINAPI
CControlPanelFolder::QueryContextMenu(
928 WCHAR szBuffer
[30] = {0};
931 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
932 this, hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
934 if (LoadStringW(shell32_hInstance
, IDS_OPEN
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
936 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
937 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, IDS_OPEN
, MFT_STRING
, szBuffer
, MFS_DEFAULT
); //FIXME identifier
941 if (LoadStringW(shell32_hInstance
, IDS_CREATELINK
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
945 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
947 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
949 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, IDS_CREATELINK
, MFT_STRING
, szBuffer
, MFS_ENABLED
); //FIXME identifier
952 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, Count
);
955 /**************************************************************************
956 * ICPanel_IContextMenu_InvokeCommand()
958 HRESULT WINAPI
CControlPanelFolder::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi
)
960 SHELLEXECUTEINFOW sei
;
961 WCHAR szPath
[MAX_PATH
];
962 char szTarget
[MAX_PATH
];
966 PIDLCPanelStruct
*pcpanel
;
967 CComPtr
<IPersistFile
> ppf
;
968 CComPtr
<IShellLinkA
> isl
;
971 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi
, lpcmi
->lpVerb
, lpcmi
->hwnd
);
973 if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(IDS_OPEN
)) //FIXME
975 ZeroMemory(&sei
, sizeof(sei
));
976 sei
.cbSize
= sizeof(sei
);
977 sei
.fMask
= SEE_MASK_INVOKEIDLIST
;
978 sei
.lpIDList
= ILCombine(pidlRoot
, apidl
[0]);
979 sei
.hwnd
= lpcmi
->hwnd
;
980 sei
.nShow
= SW_SHOWNORMAL
;
981 sei
.lpVerb
= L
"open";
983 return Execute(&sei
);
985 else if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(IDS_CREATELINK
)) //FIXME
987 if (!SHGetSpecialFolderPathW(NULL
, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
))
990 pszPath
= PathAddBackslashW(szPath
);
994 if (GetDisplayNameOf(apidl
[0], SHGDN_FORPARSING
, &strret
) != S_OK
)
997 Length
= MAX_PATH
- (pszPath
- szPath
);
998 cLength
= strlen(strret
.cStr
);
999 if (Length
< cLength
+ 5)
1005 if (MultiByteToWideChar(CP_ACP
, 0, strret
.cStr
, cLength
+ 1, pszPath
, Length
))
1013 wcscpy(pszPath
, L
" - ");
1014 cLength
= LoadStringW(shell32_hInstance
, IDS_LNK_FILE
, &pszPath
[3], Length
- 4) + 3;
1015 if (cLength
+ 5 > Length
)
1016 cLength
= Length
- 5;
1020 wcscpy(pszPath
, L
".lnk");
1022 pcpanel
= _ILGetCPanelPointer(ILFindLastID(apidl
[0]));
1025 strncpy(szTarget
, pcpanel
->szName
, MAX_PATH
);
1029 FIXME("Couldn't retrieve pointer to cpl structure\n");
1032 hResult
= CShellLink::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellLinkA
, &isl
));
1033 if (SUCCEEDED(hResult
))
1035 isl
->SetPath(szTarget
);
1036 if (SUCCEEDED(isl
->QueryInterface(IID_PPV_ARG(IPersistFile
,&ppf
))))
1037 ppf
->Save(szPath
, TRUE
);
1044 /**************************************************************************
1045 * ICPanel_IContextMenu_GetCommandString()
1048 HRESULT WINAPI
CControlPanelFolder::GetCommandString(
1055 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
1057 FIXME("unknown command string\n");
1061 /**************************************************************************
1062 * ICPanel_IContextMenu_HandleMenuMsg()
1064 HRESULT WINAPI
CControlPanelFolder::HandleMenuMsg(
1069 TRACE("ICPanel_IContextMenu_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg
, wParam
, lParam
);