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
,
315 PIDLIST_RELATIVE
*ppidl
,
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(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
376 return ShellObjectCreatorInit
<CControlPanelEnum
>(dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
379 /**************************************************************************
380 * CControlPanelFolder::BindToObject
382 HRESULT WINAPI
CControlPanelFolder::BindToObject(
383 PCUIDLIST_RELATIVE pidl
,
388 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
390 return SHELL32_BindToChild(pidlRoot
, NULL
, pidl
, riid
, ppvOut
);
393 /**************************************************************************
394 * CControlPanelFolder::BindToStorage
396 HRESULT WINAPI
CControlPanelFolder::BindToStorage(
397 PCUIDLIST_RELATIVE pidl
,
402 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
408 /**************************************************************************
409 * CControlPanelFolder::CompareIDs
412 HRESULT WINAPI
CControlPanelFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
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
);
422 /**************************************************************************
423 * CControlPanelFolder::CreateViewObject
425 HRESULT WINAPI
CControlPanelFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
427 CComPtr
<IShellView
> pShellView
;
428 HRESULT hr
= E_INVALIDARG
;
430 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner
, shdebugstr_guid(&riid
), ppvOut
);
435 if (IsEqualIID(riid
, IID_IDropTarget
)) {
436 WARN("IDropTarget not implemented\n");
438 } else if (IsEqualIID(riid
, IID_IContextMenu
)) {
439 WARN("IContextMenu not implemented\n");
441 } else if (IsEqualIID(riid
, IID_IShellView
)) {
442 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
444 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
448 TRACE("--(%p)->(interface=%p)\n", this, ppvOut
);
452 /**************************************************************************
453 * CControlPanelFolder::GetAttributesOf
455 HRESULT WINAPI
CControlPanelFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
459 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
460 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
470 while(cidl
> 0 && *apidl
)
473 SHELL32_GetItemAttributes(this, *apidl
, rgfInOut
);
477 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
478 *rgfInOut
&= ~SFGAO_VALIDATE
;
480 TRACE("-- result=0x%08x\n", *rgfInOut
);
484 /**************************************************************************
485 * CControlPanelFolder::GetUIObjectOf
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
496 HRESULT WINAPI
CControlPanelFolder::GetUIObjectOf(HWND hwndOwner
,
497 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, REFIID riid
, UINT
* prgfInOut
, LPVOID
* ppvOut
)
500 IUnknown
*pObj
= NULL
;
501 HRESULT hr
= E_INVALIDARG
;
503 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
504 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid(&riid
), prgfInOut
, ppvOut
);
509 if (IsEqualIID(riid
, IID_IContextMenu
) && (cidl
>= 1)) {
511 // create a seperate item struct
513 pObj
= (IContextMenu
*)this;
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
);
525 } else if (IsEqualIID(riid
, IID_IExtractIconW
) && (cidl
== 1)) {
526 pidl
= ILCombine(pidlRoot
, apidl
[0]);
527 pObj
= IExtractIconW_Constructor(pidl
);
530 } else if ((IsEqualIID(riid
, IID_IShellLinkW
) || IsEqualIID(riid
, IID_IShellLinkA
))
532 pidl
= ILCombine(pidlRoot
, apidl
[0]);
533 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
539 if (SUCCEEDED(hr
) && !pObj
)
544 TRACE("(%p)->hr=0x%08x\n", this, hr
);
548 /**************************************************************************
549 * CControlPanelFolder::GetDisplayNameOf
551 HRESULT WINAPI
CControlPanelFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
553 CHAR szName
[MAX_PATH
];
554 WCHAR wszName
[MAX_PATH
+1]; /* +1 for potential backslash */
555 PIDLCPanelStruct
*pCPanel
;
560 TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
566 pCPanel
= _ILGetCPanelPointer(pidl
);
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
);
574 /* take names of special folders only if it's only this folder */
575 else if (_ILIsSpecialFolder(pidl
))
577 BOOL bSimplePidl
= _ILIsPidlSimple(pidl
);
578 SFGAOF Attr
= SFGAO_FILESYSTEM
;
580 SHELL32_GetItemAttributes(this, pidl
, &Attr
);
581 if (Attr
& SFGAO_FILESYSTEM
)
583 hr
= SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, wszName
, sizeof(wszName
));
587 else if (bSimplePidl
)
589 _ILSimpleGetTextW(pidl
, wszName
, MAX_PATH
); /* append my own path */
593 FIXME("special pidl\n");
594 if (dwFlags
& SHGDN_FORPARSING
)
596 /* go deeper if needed */
599 PathAddBackslashW(wszName
);
600 cchName
= wcslen(wszName
);
602 hr
= SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, wszName
+ cchName
, MAX_PATH
+ 1 - cchName
);
608 if (!WideCharToMultiByte(CP_ACP
, 0, wszName
, -1, szName
, MAX_PATH
, NULL
, NULL
))
612 strRet
->uType
= STRRET_CSTR
;
613 lstrcpynA(strRet
->cStr
, szName
, MAX_PATH
);
615 TRACE("--(%p)->(%s)\n", this, szName
);
619 /**************************************************************************
620 * CControlPanelFolder::SetNameOf
621 * Changes the name of a file object or subfolder, possibly changing its item
622 * identifier in the process.
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
631 HRESULT WINAPI
CControlPanelFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
, /*simple pidl */
632 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
634 FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
, debugstr_w(lpName
), dwFlags
, pPidlOut
);
638 HRESULT WINAPI
CControlPanelFolder::GetDefaultSearchGUID(GUID
*pguid
)
640 FIXME("(%p)\n", this);
644 HRESULT WINAPI
CControlPanelFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
646 FIXME("(%p)\n", this);
650 HRESULT WINAPI
CControlPanelFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
652 TRACE("(%p)\n", this);
654 if (pSort
) *pSort
= 0;
655 if (pDisplay
) *pDisplay
= 0;
659 HRESULT WINAPI
CControlPanelFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
661 TRACE("(%p)\n", this);
663 if (!pcsFlags
|| iColumn
>= CONROLPANELSHELLVIEWCOLUMNS
) return E_INVALIDARG
;
664 *pcsFlags
= ControlPanelSFHeader
[iColumn
].pcsFlags
;
668 HRESULT WINAPI
CControlPanelFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
670 FIXME("(%p)\n", this);
674 HRESULT WINAPI
CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
678 TRACE("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
680 if (!psd
|| iColumn
>= CONROLPANELSHELLVIEWCOLUMNS
)
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
);
690 psd
->str
.cStr
[0] = 0x00;
691 psd
->str
.uType
= STRRET_CSTR
;
694 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
696 case 1: /* comment */
697 _ILGetFileType(pidl
, psd
->str
.cStr
, MAX_PATH
);
706 HRESULT WINAPI
CControlPanelFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
708 FIXME("(%p)\n", this);
712 /************************************************************************
713 * CControlPanelFolder::GetClassID
715 HRESULT WINAPI
CControlPanelFolder::GetClassID(CLSID
*lpClassId
)
717 TRACE("(%p)\n", this);
721 *lpClassId
= CLSID_ControlPanel
;
726 /************************************************************************
727 * CControlPanelFolder::Initialize
729 * NOTES: it makes no sense to change the pidl
731 HRESULT WINAPI
CControlPanelFolder::Initialize(LPCITEMIDLIST pidl
)
734 SHFree((LPVOID
)pidlRoot
);
736 pidlRoot
= ILClone(pidl
);
740 /**************************************************************************
741 * CControlPanelFolder::GetCurFolder
743 HRESULT WINAPI
CControlPanelFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
745 TRACE("(%p)->(%p)\n", this, pidl
);
749 *pidl
= ILClone(pidlRoot
);
753 HRESULT
CPanel_GetIconLocationW(LPCITEMIDLIST pidl
, LPWSTR szIconFile
, UINT cchMax
, int* piIndex
)
755 PIDLCPanelStruct
* pcpanel
= _ILGetCPanelPointer(pidl
);
760 MultiByteToWideChar(CP_ACP
, 0, pcpanel
->szName
, -1, szIconFile
, cchMax
);
761 *piIndex
= (int)pcpanel
->iconIdx
!= -1 ? pcpanel
->iconIdx
: 0;
767 /**************************************************************************
768 * IShellExecuteHookW Implementation
772 ExecuteAppletFromCLSID(LPOLESTR pOleStr
)
774 WCHAR wszBuf
[128], wszCmd
[MAX_PATH
];
775 DWORD cbCmd
= sizeof(wszCmd
);
777 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"CLSID\\%s\\shell\\open\\command", pOleStr
);
779 if (RegGetValueW(HKEY_CLASSES_ROOT
, wszBuf
, NULL
, RRF_RT_REG_SZ
, NULL
, (PVOID
)wszCmd
, &cbCmd
) != ERROR_SUCCESS
)
781 ERR("RegGetValueW(%ls) failed with %u\n", wszBuf
, GetLastError());
785 if (!ExpandEnvironmentStringsW(wszCmd
, wszBuf
, _countof(wszBuf
)))
788 PROCESS_INFORMATION pi
;
790 ZeroMemory(&si
, sizeof(si
));
792 if (!CreateProcessW(NULL
, wszBuf
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
795 CloseHandle(pi
.hProcess
);
796 CloseHandle(pi
.hThread
);
800 EXTERN_C
void WINAPI
Control_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
);
802 HRESULT WINAPI
CControlPanelFolder::ExecuteFromIdList(LPCITEMIDLIST pidl
)
804 PIDLCPanelStruct
*pCPanel
= _ILGetCPanelPointer(ILFindLastID(pidl
));
808 /* Is it GUID to control panel applet? */
809 IID
*piid
= _ILGetGUIDPointer(ILFindLastID(pidl
));
815 if (StringFromCLSID(*piid
, &pOleStr
) == S_OK
)
817 HRESULT hr
= ExecuteAppletFromCLSID(pOleStr
);
818 CoTaskMemFree(pOleStr
);
822 ERR("Cannot open cpanel applet\n");
826 /* Build control panel applet cmd
827 Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */
828 WCHAR wszCmd
[2*MAX_PATH
];
829 WCHAR wszAppletName
[MAX_PATH
];
831 if(!MultiByteToWideChar(CP_ACP
, 0, pCPanel
->szName
+ pCPanel
->offsDispName
, -1, wszAppletName
, MAX_PATH
))
834 StringCbPrintfW(wszCmd
, sizeof(wszCmd
), L
"rundll32 shell32.dll,Control_RunDLL \"%hs\",\"%ls\"", pCPanel
->szName
, wszAppletName
);
836 /* Start the applet */
837 TRACE("Run cpl %ls\n", wszCmd
);
839 PROCESS_INFORMATION pi
;
840 ZeroMemory(&si
, sizeof(si
));
842 if (!CreateProcessW(NULL
, wszCmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
845 CloseHandle(pi
.hProcess
);
846 CloseHandle(pi
.hThread
);
850 HRESULT WINAPI
CControlPanelFolder::Execute(LPSHELLEXECUTEINFOW psei
)
852 TRACE("(%p)->execute(%p)\n", this, psei
);
857 if (!(psei
->fMask
& SEE_MASK_IDLIST
))
859 FIXME("no idlist given!\n");
863 return ExecuteFromIdList((LPCITEMIDLIST
)psei
->lpIDList
);
866 /**************************************************************************
867 * IShellExecuteHookA Implementation
870 HRESULT WINAPI
CControlPanelFolder::Execute(LPSHELLEXECUTEINFOA psei
)
872 TRACE("(%p)->execute(%p)\n", this, psei
);
877 if (!(psei
->fMask
& SEE_MASK_IDLIST
))
879 FIXME("no idlist given!\n");
883 return ExecuteFromIdList((LPCITEMIDLIST
)psei
->lpIDList
);
886 /**************************************************************************
887 * IContextMenu2 Implementation
890 /**************************************************************************
891 * ICPanel_IContextMenu_QueryContextMenu()
893 HRESULT WINAPI
CControlPanelFolder::QueryContextMenu(
900 WCHAR szBuffer
[30] = {0};
903 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
904 this, hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
906 if (LoadStringW(shell32_hInstance
, IDS_OPEN
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
908 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
909 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, IDS_OPEN
, MFT_STRING
, szBuffer
, MFS_DEFAULT
); //FIXME identifier
913 if (LoadStringW(shell32_hInstance
, IDS_CREATELINK
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
917 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, idCmdFirst
+ Count
, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
919 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
921 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, IDS_CREATELINK
, MFT_STRING
, szBuffer
, MFS_ENABLED
); //FIXME identifier
924 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, Count
);
927 /**************************************************************************
928 * ICPanel_IContextMenu_InvokeCommand()
930 HRESULT WINAPI
CControlPanelFolder::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi
)
932 SHELLEXECUTEINFOW sei
;
933 WCHAR szPath
[MAX_PATH
];
934 char szTarget
[MAX_PATH
];
938 PIDLCPanelStruct
*pcpanel
;
939 CComPtr
<IPersistFile
> ppf
;
940 CComPtr
<IShellLinkA
> isl
;
943 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi
, lpcmi
->lpVerb
, lpcmi
->hwnd
);
945 if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(IDS_OPEN
)) //FIXME
947 ZeroMemory(&sei
, sizeof(sei
));
948 sei
.cbSize
= sizeof(sei
);
949 sei
.fMask
= SEE_MASK_INVOKEIDLIST
;
950 sei
.lpIDList
= ILCombine(pidlRoot
, apidl
[0]);
951 sei
.hwnd
= lpcmi
->hwnd
;
952 sei
.nShow
= SW_SHOWNORMAL
;
953 sei
.lpVerb
= L
"open";
955 return Execute(&sei
);
957 else if (lpcmi
->lpVerb
== MAKEINTRESOURCEA(IDS_CREATELINK
)) //FIXME
959 if (!SHGetSpecialFolderPathW(NULL
, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
))
962 pszPath
= PathAddBackslashW(szPath
);
966 if (GetDisplayNameOf(apidl
[0], SHGDN_FORPARSING
, &strret
) != S_OK
)
969 Length
= MAX_PATH
- (pszPath
- szPath
);
970 cLength
= strlen(strret
.cStr
);
971 if (Length
< cLength
+ 5)
977 if (MultiByteToWideChar(CP_ACP
, 0, strret
.cStr
, cLength
+ 1, pszPath
, Length
))
985 wcscpy(pszPath
, L
" - ");
986 cLength
= LoadStringW(shell32_hInstance
, IDS_LNK_FILE
, &pszPath
[3], Length
- 4) + 3;
987 if (cLength
+ 5 > Length
)
988 cLength
= Length
- 5;
992 wcscpy(pszPath
, L
".lnk");
994 pcpanel
= _ILGetCPanelPointer(ILFindLastID(apidl
[0]));
997 strncpy(szTarget
, pcpanel
->szName
, MAX_PATH
);
1001 FIXME("Couldn't retrieve pointer to cpl structure\n");
1004 hResult
= CShellLink::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellLinkA
, &isl
));
1005 if (SUCCEEDED(hResult
))
1007 isl
->SetPath(szTarget
);
1008 if (SUCCEEDED(isl
->QueryInterface(IID_PPV_ARG(IPersistFile
,&ppf
))))
1009 ppf
->Save(szPath
, TRUE
);
1016 /**************************************************************************
1017 * ICPanel_IContextMenu_GetCommandString()
1020 HRESULT WINAPI
CControlPanelFolder::GetCommandString(
1027 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
1029 FIXME("unknown command string\n");
1033 /**************************************************************************
1034 * ICPanel_IContextMenu_HandleMenuMsg()
1036 HRESULT WINAPI
CControlPanelFolder::HandleMenuMsg(
1041 TRACE("ICPanel_IContextMenu_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg
, wParam
, lParam
);