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 #include <precomp.h> 23 24 WINE_DEFAULT_DEBUG_CHANNEL(shell); 25 26 /*********************************************************************** 27 * control panel implementation in shell namespace 28 */ 29 30 class CControlPanelEnum : 31 public CEnumIDListBase 32 { 33 public: 34 CControlPanelEnum(); 35 ~CControlPanelEnum(); 36 HRESULT WINAPI Initialize(DWORD dwFlags, IEnumIDList* pRegEnumerator); 37 BOOL RegisterCPanelApp(LPCWSTR path); 38 int RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath); 39 BOOL CreateCPanelEnumList(DWORD dwFlags); 40 41 BEGIN_COM_MAP(CControlPanelEnum) 42 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList) 43 END_COM_MAP() 44 }; 45 46 /*********************************************************************** 47 * IShellFolder [ControlPanel] implementation 48 */ 49 50 static const shvheader ControlPanelSFHeader[] = { 51 {IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 20},/*FIXME*/ 52 {IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 80},/*FIXME*/ 53 }; 54 55 #define CONROLPANELSHELLVIEWCOLUMNS 2 56 57 CControlPanelEnum::CControlPanelEnum() 58 { 59 } 60 61 CControlPanelEnum::~CControlPanelEnum() 62 { 63 } 64 65 HRESULT WINAPI CControlPanelEnum::Initialize(DWORD dwFlags, IEnumIDList* pRegEnumerator) 66 { 67 if (CreateCPanelEnumList(dwFlags) == FALSE) 68 return E_FAIL; 69 AppendItemsFromEnumerator(pRegEnumerator); 70 return S_OK; 71 } 72 73 static LPITEMIDLIST _ILCreateCPanelApplet(LPCWSTR pszName, LPCWSTR pszDisplayName, LPCWSTR pszComment, int iIconIdx) 74 { 75 PIDLCPanelStruct *pCP; 76 LPITEMIDLIST pidl; 77 LPPIDLDATA pData; 78 int cchName, cchDisplayName, cchComment, cbData; 79 80 /* Calculate lengths of given strings */ 81 cchName = wcslen(pszName); 82 cchDisplayName = wcslen(pszDisplayName); 83 cchComment = wcslen(pszComment); 84 85 /* Allocate PIDL */ 86 cbData = sizeof(pidl->mkid.cb) + sizeof(pData->type) + sizeof(pData->u.cpanel) - sizeof(pData->u.cpanel.szName) 87 + (cchName + cchDisplayName + cchComment + 3) * sizeof(WCHAR); 88 pidl = (LPITEMIDLIST)SHAlloc(cbData + sizeof(WORD)); 89 if (!pidl) 90 return NULL; 91 92 /* Copy data to allocated memory */ 93 pidl->mkid.cb = cbData; 94 pData = (PIDLDATA *)pidl->mkid.abID; 95 pData->type = PT_CPLAPPLET; 96 97 pCP = &pData->u.cpanel; 98 pCP->dummy = 0; 99 pCP->iconIdx = iIconIdx; 100 wcscpy(pCP->szName, pszName); 101 pCP->offsDispName = cchName + 1; 102 wcscpy(pCP->szName + pCP->offsDispName, pszDisplayName); 103 pCP->offsComment = pCP->offsDispName + cchDisplayName + 1; 104 wcscpy(pCP->szName + pCP->offsComment, pszComment); 105 106 /* Add PIDL NULL terminator */ 107 *(WORD*)(pCP->szName + pCP->offsComment + cchComment + 1) = 0; 108 109 pcheck(pidl); 110 111 return pidl; 112 } 113 114 /************************************************************************** 115 * _ILGetCPanelPointer() 116 * gets a pointer to the control panel struct stored in the pidl 117 */ 118 static PIDLCPanelStruct *_ILGetCPanelPointer(LPCITEMIDLIST pidl) 119 { 120 LPPIDLDATA pdata = _ILGetDataPointer(pidl); 121 122 if (pdata && pdata->type == PT_CPLAPPLET) 123 return (PIDLCPanelStruct *) & (pdata->u.cpanel); 124 125 return NULL; 126 } 127 128 HRESULT CCPLExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut) 129 { 130 PIDLCPanelStruct *pData = _ILGetCPanelPointer(pidl); 131 if (!pData) 132 return E_FAIL; 133 134 CComPtr<IDefaultExtractIconInit> initIcon; 135 HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); 136 if (FAILED_UNEXPECTEDLY(hr)) 137 return hr; 138 139 initIcon->SetNormalIcon(pData->szName, (int)pData->iconIdx != -1 ? pData->iconIdx : 0); 140 141 return initIcon->QueryInterface(riid, ppvOut); 142 } 143 144 BOOL CControlPanelEnum::RegisterCPanelApp(LPCWSTR wpath) 145 { 146 CPlApplet* applet = Control_LoadApplet(0, wpath, NULL); 147 int iconIdx; 148 149 if (applet) 150 { 151 for (UINT i = 0; i < applet->count; ++i) 152 { 153 if (applet->info[i].idIcon > 0) 154 iconIdx = -applet->info[i].idIcon; /* negative icon index instead of icon number */ 155 else 156 iconIdx = 0; 157 158 LPITEMIDLIST pidl = _ILCreateCPanelApplet(wpath, 159 applet->info[i].name, 160 applet->info[i].info, 161 iconIdx); 162 163 if (pidl) 164 AddToEnumList(pidl); 165 } 166 Control_UnloadApplet(applet); 167 } 168 return TRUE; 169 } 170 171 int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath) 172 { 173 WCHAR name[MAX_PATH]; 174 WCHAR value[MAX_PATH]; 175 HKEY hkey; 176 177 int cnt = 0; 178 179 if (RegOpenKeyW(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) 180 { 181 int idx = 0; 182 183 for(; ; idx++) 184 { 185 DWORD nameLen = MAX_PATH; 186 DWORD valueLen = MAX_PATH; 187 WCHAR buffer[MAX_PATH]; 188 189 if (RegEnumValueW(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS) 190 break; 191 192 if (ExpandEnvironmentStringsW(value, buffer, MAX_PATH)) 193 { 194 wcscpy(value, buffer); 195 } 196 197 if (RegisterCPanelApp(value)) 198 ++cnt; 199 } 200 RegCloseKey(hkey); 201 } 202 203 return cnt; 204 } 205 206 /************************************************************************** 207 * CControlPanelEnum::CreateCPanelEnumList() 208 */ 209 BOOL CControlPanelEnum::CreateCPanelEnumList(DWORD dwFlags) 210 { 211 WCHAR szPath[MAX_PATH]; 212 WIN32_FIND_DATAW wfd; 213 HANDLE hFile; 214 215 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags); 216 217 /* enumerate the control panel applets */ 218 if (dwFlags & SHCONTF_NONFOLDERS) 219 { 220 LPWSTR p; 221 222 GetSystemDirectoryW(szPath, MAX_PATH); 223 p = PathAddBackslashW(szPath); 224 wcscpy(p, L"*.cpl"); 225 226 hFile = FindFirstFileW(szPath, &wfd); 227 228 if (hFile != INVALID_HANDLE_VALUE) 229 { 230 do 231 { 232 if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) 233 continue; 234 235 if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { 236 wcscpy(p, wfd.cFileName); 237 if (wcscmp(wfd.cFileName, L"ncpa.cpl")) 238 RegisterCPanelApp(szPath); 239 } 240 } while(FindNextFileW(hFile, &wfd)); 241 FindClose(hFile); 242 } 243 244 RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); 245 RegisterRegistryCPanelApps(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); 246 } 247 return TRUE; 248 } 249 250 CControlPanelFolder::CControlPanelFolder() 251 { 252 pidlRoot = NULL; /* absolute pidl */ 253 } 254 255 CControlPanelFolder::~CControlPanelFolder() 256 { 257 TRACE("-- destroying IShellFolder(%p)\n", this); 258 SHFree(pidlRoot); 259 } 260 261 /************************************************************************** 262 * CControlPanelFolder::ParseDisplayName 263 */ 264 HRESULT WINAPI CControlPanelFolder::ParseDisplayName( 265 HWND hwndOwner, 266 LPBC pbc, 267 LPOLESTR lpszDisplayName, 268 DWORD *pchEaten, 269 PIDLIST_RELATIVE *ppidl, 270 DWORD *pdwAttributes) 271 { 272 /* We only support parsing guid names */ 273 return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes); 274 } 275 276 /************************************************************************** 277 * CControlPanelFolder::EnumObjects 278 */ 279 HRESULT WINAPI CControlPanelFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) 280 { 281 CComPtr<IEnumIDList> pRegEnumerator; 282 m_regFolder->EnumObjects(hwndOwner, dwFlags, &pRegEnumerator); 283 284 return ShellObjectCreatorInit<CControlPanelEnum>(dwFlags, pRegEnumerator, IID_PPV_ARG(IEnumIDList, ppEnumIDList)); 285 } 286 287 /************************************************************************** 288 * CControlPanelFolder::BindToObject 289 */ 290 HRESULT WINAPI CControlPanelFolder::BindToObject( 291 PCUIDLIST_RELATIVE pidl, 292 LPBC pbcReserved, 293 REFIID riid, 294 LPVOID *ppvOut) 295 { 296 return m_regFolder->BindToObject(pidl, pbcReserved, riid, ppvOut); 297 } 298 299 /************************************************************************** 300 * CControlPanelFolder::BindToStorage 301 */ 302 HRESULT WINAPI CControlPanelFolder::BindToStorage( 303 PCUIDLIST_RELATIVE pidl, 304 LPBC pbcReserved, 305 REFIID riid, 306 LPVOID *ppvOut) 307 { 308 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut); 309 310 *ppvOut = NULL; 311 return E_NOTIMPL; 312 } 313 314 /************************************************************************** 315 * CControlPanelFolder::CompareIDs 316 */ 317 HRESULT WINAPI CControlPanelFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) 318 { 319 /* Dont use SHELL32_CompareGuidItems because it would cause guid items to come first */ 320 if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2)) 321 { 322 return SHELL32_CompareDetails(this, lParam, pidl1, pidl2); 323 } 324 PIDLCPanelStruct *pData1 = _ILGetCPanelPointer(pidl1); 325 PIDLCPanelStruct *pData2 = _ILGetCPanelPointer(pidl2); 326 327 if (!pData1 || !pData2 || LOWORD(lParam)>= CONROLPANELSHELLVIEWCOLUMNS) 328 return E_INVALIDARG; 329 330 int result; 331 switch(LOWORD(lParam)) 332 { 333 case 0: /* name */ 334 result = wcsicmp(pData1->szName + pData1->offsDispName, pData2->szName + pData2->offsDispName); 335 break; 336 case 1: /* comment */ 337 result = wcsicmp(pData1->szName + pData1->offsComment, pData2->szName + pData2->offsComment); 338 break; 339 default: 340 ERR("Got wrong lParam!\n"); 341 return E_INVALIDARG; 342 } 343 344 return MAKE_COMPARE_HRESULT(result); 345 } 346 347 /************************************************************************** 348 * CControlPanelFolder::CreateViewObject 349 */ 350 HRESULT WINAPI CControlPanelFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut) 351 { 352 CComPtr<IShellView> pShellView; 353 HRESULT hr = E_INVALIDARG; 354 355 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner, shdebugstr_guid(&riid), ppvOut); 356 357 if (ppvOut) { 358 *ppvOut = NULL; 359 360 if (IsEqualIID(riid, IID_IDropTarget)) { 361 WARN("IDropTarget not implemented\n"); 362 hr = E_NOTIMPL; 363 } else if (IsEqualIID(riid, IID_IContextMenu)) { 364 WARN("IContextMenu not implemented\n"); 365 hr = E_NOTIMPL; 366 } else if (IsEqualIID(riid, IID_IShellView)) { 367 SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this}; 368 hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut); 369 } 370 } 371 TRACE("--(%p)->(interface=%p)\n", this, ppvOut); 372 return hr; 373 } 374 375 /************************************************************************** 376 * CControlPanelFolder::GetAttributesOf 377 */ 378 HRESULT WINAPI CControlPanelFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut) 379 { 380 HRESULT hr = S_OK; 381 static const DWORD dwControlPanelAttributes = 382 SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK; 383 384 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", 385 this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); 386 387 if (!rgfInOut) 388 return E_INVALIDARG; 389 if (cidl && !apidl) 390 return E_INVALIDARG; 391 392 if (*rgfInOut == 0) 393 *rgfInOut = ~0; 394 395 if (!cidl) 396 { 397 *rgfInOut &= dwControlPanelAttributes; 398 } 399 else 400 { 401 while(cidl > 0 && *apidl) 402 { 403 pdump(*apidl); 404 if (_ILIsCPanelStruct(*apidl)) 405 *rgfInOut &= SFGAO_CANLINK; 406 else if (_ILIsSpecialFolder(*apidl)) 407 m_regFolder->GetAttributesOf(1, apidl, rgfInOut); 408 else 409 ERR("Got an unkown pidl here!\n"); 410 apidl++; 411 cidl--; 412 } 413 } 414 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */ 415 *rgfInOut &= ~SFGAO_VALIDATE; 416 417 TRACE("-- result=0x%08x\n", *rgfInOut); 418 return hr; 419 } 420 421 /************************************************************************** 422 * CControlPanelFolder::GetUIObjectOf 423 * 424 * PARAMETERS 425 * HWND hwndOwner, //[in ] Parent window for any output 426 * UINT cidl, //[in ] array size 427 * LPCITEMIDLIST* apidl, //[in ] simple pidl array 428 * REFIID riid, //[in ] Requested Interface 429 * UINT* prgfInOut, //[ ] reserved 430 * LPVOID* ppvObject) //[out] Resulting Interface 431 * 432 */ 433 HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner, 434 UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) 435 { 436 LPVOID pObj = NULL; 437 HRESULT hr = E_INVALIDARG; 438 439 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", 440 this, hwndOwner, cidl, apidl, shdebugstr_guid(&riid), prgfInOut, ppvOut); 441 442 if (ppvOut) { 443 *ppvOut = NULL; 444 445 if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) { 446 447 /* HACK: We should use callbacks from CDefaultContextMenu instead of creating one on our own */ 448 BOOL bHasCpl = FALSE; 449 for (UINT i = 0; i < cidl; i++) 450 { 451 if(_ILIsCPanelStruct(apidl[i])) 452 { 453 bHasCpl = TRUE; 454 } 455 } 456 457 if (bHasCpl) 458 hr = ShellObjectCreatorInit<CCPLItemMenu>(cidl, apidl, riid, &pObj); 459 else 460 hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj); 461 } else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) { 462 hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, TRUE, (IDataObject **)&pObj); 463 } else if ((IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && (cidl == 1)) { 464 if (_ILGetCPanelPointer(apidl[0])) 465 hr = CCPLExtractIcon_CreateInstance(this, apidl[0], riid, &pObj); 466 else 467 hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj); 468 } else { 469 hr = E_NOINTERFACE; 470 } 471 472 if (SUCCEEDED(hr) && !pObj) 473 hr = E_OUTOFMEMORY; 474 475 *ppvOut = pObj; 476 } 477 TRACE("(%p)->hr=0x%08x\n", this, hr); 478 return hr; 479 } 480 481 /************************************************************************** 482 * CControlPanelFolder::GetDisplayNameOf 483 */ 484 HRESULT WINAPI CControlPanelFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) 485 { 486 if (!pidl) 487 return S_FALSE; 488 489 PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(pidl); 490 491 if (pCPanel) 492 { 493 return SHSetStrRet(strRet, pCPanel->szName + pCPanel->offsDispName); 494 } 495 else if (_ILIsSpecialFolder(pidl)) 496 { 497 return m_regFolder->GetDisplayNameOf(pidl, dwFlags, strRet); 498 } 499 500 return E_FAIL; 501 } 502 503 /************************************************************************** 504 * CControlPanelFolder::SetNameOf 505 * Changes the name of a file object or subfolder, possibly changing its item 506 * identifier in the process. 507 * 508 * PARAMETERS 509 * HWND hwndOwner, //[in ] Owner window for output 510 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change 511 * LPCOLESTR lpszName, //[in ] the items new display name 512 * DWORD dwFlags, //[in ] SHGNO formatting flags 513 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned 514 */ 515 HRESULT WINAPI CControlPanelFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /*simple pidl */ 516 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut) 517 { 518 FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut); 519 return E_FAIL; 520 } 521 522 HRESULT WINAPI CControlPanelFolder::GetDefaultSearchGUID(GUID *pguid) 523 { 524 FIXME("(%p)\n", this); 525 return E_NOTIMPL; 526 } 527 528 HRESULT WINAPI CControlPanelFolder::EnumSearches(IEnumExtraSearch **ppenum) 529 { 530 FIXME("(%p)\n", this); 531 return E_NOTIMPL; 532 } 533 534 HRESULT WINAPI CControlPanelFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay) 535 { 536 TRACE("(%p)\n", this); 537 538 if (pSort) *pSort = 0; 539 if (pDisplay) *pDisplay = 0; 540 return S_OK; 541 } 542 543 HRESULT WINAPI CControlPanelFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags) 544 { 545 TRACE("(%p)\n", this); 546 547 if (!pcsFlags || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) return E_INVALIDARG; 548 *pcsFlags = ControlPanelSFHeader[iColumn].pcsFlags; 549 return S_OK; 550 } 551 552 HRESULT WINAPI CControlPanelFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv) 553 { 554 FIXME("(%p)\n", this); 555 return E_NOTIMPL; 556 } 557 558 HRESULT WINAPI CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd) 559 { 560 if (!psd || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) 561 return E_INVALIDARG; 562 563 if (!pidl) 564 { 565 psd->fmt = ControlPanelSFHeader[iColumn].fmt; 566 psd->cxChar = ControlPanelSFHeader[iColumn].cxChar; 567 return SHSetStrRet(&psd->str, shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid); 568 } 569 else if (_ILIsSpecialFolder(pidl)) 570 { 571 return m_regFolder->GetDetailsOf(pidl, iColumn, psd); 572 } 573 else 574 { 575 PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(pidl); 576 577 if (!pCPanel) 578 return E_FAIL; 579 580 switch(iColumn) 581 { 582 case 0: /* name */ 583 return SHSetStrRet(&psd->str, pCPanel->szName + pCPanel->offsDispName); 584 case 1: /* comment */ 585 return SHSetStrRet(&psd->str, pCPanel->szName + pCPanel->offsComment); 586 } 587 } 588 589 return S_OK; 590 } 591 592 HRESULT WINAPI CControlPanelFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid) 593 { 594 FIXME("(%p)\n", this); 595 return E_NOTIMPL; 596 } 597 598 /************************************************************************ 599 * CControlPanelFolder::GetClassID 600 */ 601 HRESULT WINAPI CControlPanelFolder::GetClassID(CLSID *lpClassId) 602 { 603 TRACE("(%p)\n", this); 604 605 if (!lpClassId) 606 return E_POINTER; 607 *lpClassId = CLSID_ControlPanel; 608 609 return S_OK; 610 } 611 612 /************************************************************************ 613 * CControlPanelFolder::Initialize 614 * 615 * NOTES: it makes no sense to change the pidl 616 */ 617 HRESULT WINAPI CControlPanelFolder::Initialize(PCIDLIST_ABSOLUTE pidl) 618 { 619 if (pidlRoot) 620 SHFree((LPVOID)pidlRoot); 621 622 pidlRoot = ILClone(pidl); 623 624 /* Create the inner reg folder */ 625 HRESULT hr; 626 hr = CRegFolder_CreateInstance(&CLSID_ControlPanel, 627 pidlRoot, 628 L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", 629 L"ControlPanel", 630 IID_PPV_ARG(IShellFolder2, &m_regFolder)); 631 if (FAILED_UNEXPECTEDLY(hr)) 632 return hr; 633 634 return S_OK; 635 } 636 637 /************************************************************************** 638 * CControlPanelFolder::GetCurFolder 639 */ 640 HRESULT WINAPI CControlPanelFolder::GetCurFolder(PIDLIST_ABSOLUTE * pidl) 641 { 642 TRACE("(%p)->(%p)\n", this, pidl); 643 644 if (!pidl) 645 return E_POINTER; 646 *pidl = ILClone(pidlRoot); 647 return S_OK; 648 } 649 650 CCPLItemMenu::CCPLItemMenu() 651 { 652 m_apidl = NULL; 653 m_cidl = 0; 654 } 655 656 HRESULT WINAPI CCPLItemMenu::Initialize(UINT cidl, PCUITEMID_CHILD_ARRAY apidl) 657 { 658 m_cidl = cidl; 659 m_apidl = _ILCopyaPidl(apidl, m_cidl); 660 if (m_cidl && !m_apidl) 661 return E_OUTOFMEMORY; 662 663 return S_OK; 664 } 665 666 CCPLItemMenu::~CCPLItemMenu() 667 { 668 _ILFreeaPidl(m_apidl, m_cidl); 669 } 670 671 HRESULT WINAPI CCPLItemMenu::QueryContextMenu( 672 HMENU hMenu, 673 UINT indexMenu, 674 UINT idCmdFirst, 675 UINT idCmdLast, 676 UINT uFlags) 677 { 678 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst, MFT_STRING, MAKEINTRESOURCEW(IDS_OPEN), MFS_DEFAULT); 679 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDC_STATIC, MFT_SEPARATOR, NULL, MFS_ENABLED); 680 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 1, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED); 681 682 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 2); 683 } 684 685 EXTERN_C 686 void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow); 687 688 /************************************************************************** 689 * ICPanel_IContextMenu_InvokeCommand() 690 */ 691 HRESULT WINAPI CCPLItemMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) 692 { 693 HRESULT hResult; 694 695 PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(m_apidl[0]); 696 if(!pCPanel) 697 return E_FAIL; 698 699 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd); 700 701 if (lpcmi->lpVerb == MAKEINTRESOURCEA(0)) 702 { 703 /* Hardcode the command here; Executing a cpl file would be fine but we also need to run things like console.dll */ 704 WCHAR wszParams[MAX_PATH]; 705 PCWSTR wszFile = L"rundll32.exe"; 706 PCWSTR wszFormat = L"shell32.dll,Control_RunDLL %s,%s"; 707 708 wsprintfW(wszParams, wszFormat, pCPanel->szName, pCPanel->szName + pCPanel->offsDispName); 709 710 /* Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */ 711 ShellExecuteW(NULL, NULL, wszFile, wszParams, NULL, 0); 712 } 713 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(1)) //FIXME 714 { 715 CComPtr<IDataObject> pDataObj; 716 LPITEMIDLIST pidl = _ILCreateControlPanel(); 717 718 hResult = SHCreateDataObject(pidl, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj)); 719 if (FAILED(hResult)) 720 return hResult; 721 722 SHFree(pidl); 723 724 //FIXME: Use SHCreateLinks 725 CComPtr<IShellFolder> psf; 726 CComPtr<IDropTarget> pDT; 727 728 hResult = SHGetDesktopFolder(&psf); 729 if (FAILED(hResult)) 730 return hResult; 731 732 hResult = psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pDT)); 733 if (FAILED(hResult)) 734 return hResult; 735 736 SHSimulateDrop(pDT, pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL); 737 } 738 return S_OK; 739 } 740 741 /************************************************************************** 742 * ICPanel_IContextMenu_GetCommandString() 743 * 744 */ 745 HRESULT WINAPI CCPLItemMenu::GetCommandString( 746 UINT_PTR idCommand, 747 UINT uFlags, 748 UINT* lpReserved, 749 LPSTR lpszName, 750 UINT uMaxNameLen) 751 { 752 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); 753 754 FIXME("unknown command string\n"); 755 return E_FAIL; 756 } 757 758 /************************************************************************** 759 * ICPanel_IContextMenu_HandleMenuMsg() 760 */ 761 HRESULT WINAPI CCPLItemMenu::HandleMenuMsg( 762 UINT uMsg, 763 WPARAM wParam, 764 LPARAM lParam) 765 { 766 TRACE("ICPanel_IContextMenu_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam); 767 768 return E_NOTIMPL; 769 } 770