WINE_DEFAULT_DEBUG_CHANNEL (shell);
+HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf,
+ HWND hwnd,
+ IDataObject *pdtobj,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
+ return S_OK;
+
+ PIDLIST_ABSOLUTE pidlFolder;
+ PUITEMID_CHILD *apidl;
+ UINT cidl;
+ HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ if (_ILIsMyComputer(apidl[0]))
+ {
+ if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL))
+ hr = E_FAIL;
+ }
+ else if (_ILIsDesktop(apidl[0]))
+ {
+ if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
+ hr = E_FAIL;
+ }
+ else if (_ILIsNetHood(apidl[0]))
+ {
+ // FIXME path!
+ if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe",
+ L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
+ NULL, SW_SHOWDEFAULT))
+ hr = E_FAIL;
+ }
+ else if (_ILIsBitBucket(apidl[0]))
+ {
+ /* FIXME: detect the drive path of bitbucket if appropiate */
+ if (!SH_ShowRecycleBinProperties(L'C'))
+ hr = E_FAIL;
+ }
+
+ SHFree(pidlFolder);
+ _ILFreeaPidl(apidl, cidl);
+
+ return hr;
+}
+
+HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
+ HWND hwnd,
+ UINT cidl,
+ PCUITEMID_CHILD_ARRAY apidl,
+ IShellFolder *psf,
+ IContextMenu **ppcm)
+{
+ HKEY hKeys[10];
+ UINT cKeys = 0;
+
+ GUID *pGuid = _ILGetGUIDPointer(apidl[0]);
+ if (pGuid)
+ {
+ LPOLESTR pwszCLSID;
+ WCHAR key[60];
+
+ wcscpy(key, L"CLSID\\");
+ HRESULT hr = StringFromCLSID(*pGuid, &pwszCLSID);
+ if (hr == S_OK)
+ {
+ wcscpy(&key[6], pwszCLSID);
+ AddClassKeyToArray(key, hKeys, &cKeys);
+ }
+ }
+ AddClassKeyToArray(L"Folder", hKeys, &cKeys);
+
+ return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, cKeys, hKeys, ppcm);
+}
+
HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut)
{
CComPtr<IDefaultExtractIconInit> initIcon;
return initIcon->QueryInterface(iid, ppvOut);
}
+class CRegFolderEnum :
+ public CEnumIDListBase
+{
+ public:
+ CRegFolderEnum();
+ ~CRegFolderEnum();
+ HRESULT Initialize(LPCWSTR lpszEnumKeyName, DWORD dwFlags);
+ HRESULT AddItemsFromKey(HKEY hkey_root, LPCWSTR szRepPath);
+
+ BEGIN_COM_MAP(CRegFolderEnum)
+ COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
+ END_COM_MAP()
+};
+
+CRegFolderEnum::CRegFolderEnum()
+{
+}
+
+CRegFolderEnum::~CRegFolderEnum()
+{
+}
+
+HRESULT CRegFolderEnum::Initialize(LPCWSTR lpszEnumKeyName, DWORD dwFlags)
+{
+ WCHAR KeyName[MAX_PATH];
+ static const WCHAR KeyNameFormat[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\%s\\Namespace";
+
+ if (!(dwFlags & SHCONTF_FOLDERS))
+ return S_OK;
+
+ HRESULT hr = StringCchPrintfW(KeyName, MAX_PATH, KeyNameFormat, lpszEnumKeyName);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ AddItemsFromKey(HKEY_LOCAL_MACHINE, KeyName);
+ AddItemsFromKey(HKEY_CURRENT_USER, KeyName);
+
+ return S_OK;
+}
+
+HRESULT CRegFolderEnum::AddItemsFromKey(HKEY hkey_root, LPCWSTR szRepPath)
+{
+ WCHAR name[MAX_PATH];
+ HKEY hkey;
+
+ if (RegOpenKeyW(hkey_root, szRepPath, &hkey) != ERROR_SUCCESS)
+ return S_FALSE;
+
+ for (int idx = 0; ; idx++)
+ {
+ if (RegEnumKeyW(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS)
+ break;
+
+ /* If the name of the key is not a guid try to get the default value of the key */
+ if (name[0] != L'{')
+ {
+ DWORD dwSize = sizeof(name);
+ RegGetValueW(hkey, name, NULL, RRF_RT_REG_SZ, NULL, name, &dwSize);
+ }
+
+ if (*name == '{')
+ {
+ LPITEMIDLIST pidl = _ILCreateGuidFromStrW(name);
+
+ if (pidl)
+ AddToEnumList(pidl);
+ }
+ }
+
+ RegCloseKey(hkey);
+
+ return S_OK;
+}
+
class CRegFolder :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IShellFolder2
private:
GUID m_guid;
CAtlStringW m_rootPath;
+ CAtlStringW m_enumKeyName;
CComHeapPtr<ITEMIDLIST> m_pidlRoot;
HRESULT GetGuidItemAttributes (LPCITEMIDLIST pidl, LPDWORD pdwAttributes);
public:
CRegFolder();
~CRegFolder();
- HRESULT WINAPI Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath);
+ HRESULT WINAPI Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, LPCWSTR lpszEnumKeyName);
// IShellFolder
virtual HRESULT WINAPI ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes);
{
}
-HRESULT WINAPI CRegFolder::Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath)
+HRESULT WINAPI CRegFolder::Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, LPCWSTR lpszEnumKeyName)
{
memcpy(&m_guid, pGuid, sizeof(m_guid));
if (!m_rootPath)
return E_OUTOFMEMORY;
+ m_enumKeyName = lpszEnumKeyName;
+ if (!m_enumKeyName)
+ return E_OUTOFMEMORY;
+
m_pidlRoot.Attach(ILClone(pidlRoot));
if (!m_pidlRoot)
return E_OUTOFMEMORY;
HRESULT CRegFolder::GetGuidItemAttributes (LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
{
+ DWORD dwAttributes = *pdwAttributes;
+
/* First try to get them from the registry */
- if (HCR_GetFolderAttributes(pidl, pdwAttributes) && *pdwAttributes)
+ if (!HCR_GetFolderAttributes(pidl, pdwAttributes))
{
- return S_OK;
+ /* We couldn't get anything */
+ *pdwAttributes = 0;
}
- *pdwAttributes &= SFGAO_CANLINK;
+ /* Items have more attributes when on desktop */
+ if (_ILIsDesktop(m_pidlRoot))
+ {
+ *pdwAttributes |= (dwAttributes & (SFGAO_CANLINK|SFGAO_CANDELETE|SFGAO_CANRENAME|SFGAO_HASPROPSHEET));
+ }
+
+ /* In any case, links can be created */
+ if (*pdwAttributes == NULL)
+ {
+ *pdwAttributes |= (dwAttributes & SFGAO_CANLINK);
+ }
return S_OK;
}
HRESULT WINAPI CRegFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
{
- return E_NOTIMPL;
+ return ShellObjectCreatorInit<CRegFolderEnum>(m_enumKeyName, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
}
HRESULT WINAPI CRegFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
return E_INVALIDARG;
}
- LPITEMIDLIST pidlChild = ILCloneFirst (pidl);
- if (!pidlChild)
- return E_OUTOFMEMORY;
-
- CComPtr<IShellFolder> psf;
- hr = SHELL32_CoCreateInitSF(m_pidlRoot, NULL, pidlChild, pGUID, -1, IID_PPV_ARG(IShellFolder, &psf));
- ILFree(pidlChild);
- if (FAILED(hr))
+ hr = SHELL32_BindToSF(m_pidlRoot, NULL, pidl, pGUID, riid, ppvOut);
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- if (_ILIsPidlSimple (pidl))
- {
- return psf->QueryInterface(riid, ppvOut);
- }
- else
- {
- return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut);
- }
+ return S_OK;
}
HRESULT WINAPI CRegFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
{
hr = CGuidItemExtractIcon_CreateInstance(apidl[0], riid, &pObj);
}
+ else if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
+ {
+ if (!_ILGetGUIDPointer (apidl[0]))
+ {
+ ERR("Got non guid item!\n");
+ return E_FAIL;
+ }
+
+ hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
+ }
+ else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
+ {
+ hr = IDataObject_Constructor (hwndOwner, m_pidlRoot, apidl, cidl, (IDataObject **)&pObj);
+ }
else
+ {
hr = E_NOINTERFACE;
+ }
*ppvOut = pObj;
return hr;
HRESULT WINAPI CRegFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{
- if (!strRet || !_ILIsSpecialFolder(pidl))
+ if (!strRet || (!_ILIsSpecialFolder(pidl) && pidl != NULL))
return E_INVALIDARG;
- if (!pidl->mkid.cb)
+ if (!pidl || !pidl->mkid.cb)
{
if ((GET_SHGDN_RELATION(dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING))
{
}
else
{
- return HCR_GetClassName(m_guid, strRet);
+ BOOL bRet;
+ WCHAR wstrName[MAX_PATH+1];
+ bRet = HCR_GetClassNameW(m_guid, wstrName, MAX_PATH);
+ if (!bRet)
+ return E_FAIL;
+
+ return SHSetStrRet(strRet, wstrName);
+
}
}
HRESULT WINAPI CRegFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
{
- if (!psd || iColumn >= 2)
+ if (!psd)
return E_INVALIDARG;
GUID const *clsid = _ILGetGUIDPointer (pidl);
return E_INVALIDARG;
}
+ if (iColumn >= 3)
+ {
+ /* Return an empty string when we area asked for a column we don't support.
+ Only the regfolder is supposed to do this as it supports less columns compared to other folder
+ and its contents are supposed to be presented alongside items that support more columns. */
+ return SHSetStrRet(&psd->str, "");
+ }
+
switch(iColumn)
{
case 0: /* name */
return GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
- case 1: /* comment */
+ case 1: /* comments */
HKEY hKey;
- if (HCR_RegOpenClassIDKey(*clsid, &hKey))
- {
- psd->str.cStr[0] = 0x00;
- psd->str.uType = STRRET_CSTR;
- RegLoadMUIStringA(hKey, "InfoTip", psd->str.cStr, MAX_PATH, NULL, 0, NULL);
- RegCloseKey(hKey);
- return S_OK;
- }
+ if (!HCR_RegOpenClassIDKey(*clsid, &hKey))
+ return SHSetStrRet(&psd->str, "");
+
+ psd->str.cStr[0] = 0x00;
+ psd->str.uType = STRRET_CSTR;
+ RegLoadMUIStringA(hKey, "InfoTip", psd->str.cStr, MAX_PATH, NULL, 0, NULL);
+ RegCloseKey(hKey);
+ return S_OK;
+ case 2: /* type */
+ //return SHSetStrRet(&psd->str, resource_id); /* FIXME: translate */
+ return SHSetStrRet(&psd->str, "System Folder");
}
return E_FAIL;
}
}
/* In latest windows version this is exported but it takes different arguments! */
-HRESULT CRegFolder_CreateInstance(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, REFIID riid, void **ppv)
+HRESULT CRegFolder_CreateInstance(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, LPCWSTR lpszEnumKeyName, REFIID riid, void **ppv)
{
- return ShellObjectCreatorInit<CRegFolder>(pGuid, pidlRoot, lpszPath, riid, ppv);
+ return ShellObjectCreatorInit<CRegFolder>(pGuid, pidlRoot, lpszPath, lpszEnumKeyName, riid, ppv);
}