WINE_DEFAULT_DEBUG_CHANNEL (shell);
+#define HACKY_UNC_PATHS
+
+#ifdef HACKY_UNC_PATHS
+LPITEMIDLIST ILCreateFromNetworkPlaceW(LPCWSTR lpNetworkPlace)
+{
+ int cbData = sizeof(WORD) + sizeof(WCHAR) * (wcslen(lpNetworkPlace)+1);
+ LPITEMIDLIST pidl = (LPITEMIDLIST)SHAlloc(cbData + sizeof(WORD));
+ if (!pidl)
+ return NULL;
+
+ pidl->mkid.cb = cbData;
+ wcscpy((WCHAR*)&pidl->mkid.abID[0], lpNetworkPlace);
+ *(WORD*)((char*)pidl + cbData) = 0;
+
+ return pidl;
+}
+#endif
+
/***********************************************************************
* IShellFolder implementation
*/
+HRESULT CNetFolderExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
+{
+ CComPtr<IDefaultExtractIconInit> initIcon;
+ HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_NETWORK_FOLDER);
+
+ return initIcon->QueryInterface(riid, ppvOut);
+}
+
+HRESULT CALLBACK NetFolderMenuCallback(IShellFolder *psf,
+ HWND hwnd,
+ IDataObject *pdtobj,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case DFM_MERGECONTEXTMENU:
+ return S_OK;
+ case DFM_INVOKECOMMAND:
+ case DFM_INVOKECOMMANDEX:
+ case DFM_GETDEFSTATICID: // Required for Windows 7 to pick a default
+ return S_FALSE;
+ }
+ return E_NOTIMPL;
+}
+
+class CNetFolderEnum :
+ public CEnumIDListBase
+{
+ public:
+ CNetFolderEnum();
+ ~CNetFolderEnum();
+ HRESULT WINAPI Initialize(HWND hwndOwner, DWORD dwFlags);
+ BOOL CreateMyCompEnumList(DWORD dwFlags);
+ BOOL EnumerateRec(LPNETRESOURCE lpNet);
+
+ BEGIN_COM_MAP(CNetFolderEnum)
+ COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
+ END_COM_MAP()
+};
+
static shvheader NetworkPlacesSFHeader[] = {
- {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
- {IDS_SHV_COLUMN13, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
+ {IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
+ {IDS_SHV_COLUMN_CATEGORY, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN_WORKGROUP, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
- {IDS_SHV_NETWORKLOCATION, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}
+ {IDS_SHV_COLUMN_NETLOCATION, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}
};
#define COLUMN_NAME 0
#define NETWORKPLACESSHELLVIEWCOLUMNS 4
-CNetFolder::CNetFolder()
+CNetFolderEnum::CNetFolderEnum()
{
- pidlRoot = NULL;
}
-CNetFolder::~CNetFolder()
+CNetFolderEnum::~CNetFolderEnum()
{
- TRACE("-- destroying IShellFolder(%p)\n", this);
- SHFree(pidlRoot);
}
-HRESULT WINAPI CNetFolder::FinalConstruct()
+HRESULT WINAPI CNetFolderEnum::Initialize(HWND hwndOwner, DWORD dwFlags)
{
- pidlRoot = _ILCreateGuid(PT_GUID, CLSID_NetworkPlaces); /* my qualified pidl */
- if (pidlRoot == NULL)
- return E_OUTOFMEMORY;
+ if (CreateMyCompEnumList(dwFlags) == FALSE)
+ return E_FAIL;
+
return S_OK;
}
+/**************************************************************************
+ * CDrivesFolderEnum::CreateMyCompEnumList()
+ */
+
+BOOL CNetFolderEnum::EnumerateRec(LPNETRESOURCE lpNet)
+{
+ BOOL bRet = TRUE;
+ DWORD dRet;
+ HANDLE hEnum;
+ LPNETRESOURCE lpRes;
+ DWORD dSize = 0x1000;
+ DWORD dCount = -1;
+ LPNETRESOURCE lpCur;
+
+ dRet = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, lpNet, &hEnum);
+ if (dRet != WN_SUCCESS)
+ {
+ ERR("WNetOpenEnum() failed: %x\n", dRet);
+ return FALSE;
+ }
+
+ lpRes = (LPNETRESOURCE)CoTaskMemAlloc(dSize);
+ if (!lpRes)
+ {
+ ERR("CoTaskMemAlloc() failed\n");
+ WNetCloseEnum(hEnum);
+ return FALSE;
+ }
+
+ do
+ {
+ dSize = 0x1000;
+ dCount = -1;
+
+ memset(lpRes, 0, dSize);
+ dRet = WNetEnumResource(hEnum, &dCount, lpRes, &dSize);
+ if (dRet == WN_SUCCESS || dRet == WN_MORE_DATA)
+ {
+ lpCur = lpRes;
+ for (; dCount; dCount--)
+ {
+ TRACE("lpRemoteName: %S\n", lpCur->lpRemoteName);
+
+ if ((lpCur->dwUsage & RESOURCEUSAGE_CONTAINER) == RESOURCEUSAGE_CONTAINER)
+ {
+ TRACE("Found provider: %S\n", lpCur->lpProvider);
+ EnumerateRec(lpCur);
+ }
+ else
+ {
+ LPITEMIDLIST pidl;
+
+#ifdef HACKY_UNC_PATHS
+ pidl = ILCreateFromNetworkPlaceW(lpCur->lpRemoteName);
+#endif
+ if (pidl != NULL)
+ bRet = AddToEnumList(pidl);
+ else
+ {
+ ERR("ILCreateFromPathW() failed\n");
+ bRet = FALSE;
+ break;
+ }
+ }
+
+ lpCur++;
+ }
+ }
+ } while (dRet != WN_NO_MORE_ENTRIES);
+
+ CoTaskMemFree(lpRes);
+ WNetCloseEnum(hEnum);
+
+ TRACE("Done: %u\n", bRet);
+
+ return bRet;
+}
+
+BOOL CNetFolderEnum::CreateMyCompEnumList(DWORD dwFlags)
+{
+ BOOL bRet = TRUE;
+
+ TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
+
+ /* enumerate the folders */
+ if (dwFlags & SHCONTF_FOLDERS)
+ {
+ bRet = EnumerateRec(NULL);
+ }
+
+ return bRet;
+}
+
+CNetFolder::CNetFolder()
+{
+ pidlRoot = NULL;
+}
+
+CNetFolder::~CNetFolder()
+{
+ if (pidlRoot)
+ SHFree(pidlRoot);
+}
+
/**************************************************************************
* CNetFolder::ParseDisplayName
*/
DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
{
HRESULT hr = E_UNEXPECTED;
+#ifdef HACKY_UNC_PATHS
+ /* FIXME: the code below is an ugly hack */
+
+ /* Can we use a CFSFolder on that path? */
+ DWORD attrs = GetFileAttributes(lpszDisplayName);
+ if ((attrs & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ if (pchEaten)
+ *pchEaten = 0; /* strange but like the original */
+
+ /* YES WE CAN */
+
+ /* Create our hacky pidl */
+ LPITEMIDLIST pidl = ILCreateFromNetworkPlaceW(lpszDisplayName);
+
+ *ppidl = pidl;
+ if (pdwAttributes)
+ *pdwAttributes = SFGAO_FILESYSTEM | SFGAO_CANLINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR;
+ return S_OK;
+ }
+#endif
TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName),
*/
HRESULT WINAPI CNetFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
{
- TRACE("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this,
- hwndOwner, dwFlags, ppEnumIDList);
-
- *ppEnumIDList = NULL; //IEnumIDList_Constructor();
-
- TRACE("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
- return S_FALSE;
- // return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
+ return ShellObjectCreatorInit<CNetFolderEnum>(hwndOwner, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
}
/**************************************************************************
*/
HRESULT WINAPI CNetFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
{
- TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
- pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
-
- return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
+#ifdef HACKY_UNC_PATHS
+ /* Create the target folder info */
+ PERSIST_FOLDER_TARGET_INFO pfti = {0};
+ pfti.dwAttributes = -1;
+ pfti.csidl = -1;
+ StringCchCopyW(pfti.szTargetParsingName, MAX_PATH, (WCHAR*)pidl->mkid.abID);
+
+ return SHELL32_BindToSF(pidlRoot, &pfti, pidl, &CLSID_ShellFSFolder, riid, ppvOut);
+#else
+ return E_NOTIMPL;
+#endif
}
/**************************************************************************
HRESULT WINAPI CNetFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
{
- int nReturn;
-
- TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
- nReturn = SHELL32_CompareIDs(this, lParam, pidl1, pidl2);
- TRACE("-- %i\n", nReturn);
- return nReturn;
+ return E_NOTIMPL;
}
/**************************************************************************
}
else if (IsEqualIID(riid, IID_IShellView))
{
- hr = IShellView_Constructor((IShellFolder *)this, &pShellView);
- if (pShellView)
- {
- hr = pShellView->QueryInterface(riid, ppvOut);
- }
+ SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this};
+ hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
}
TRACE("-- (%p)->(interface=%p)\n", this, ppvOut);
return hr;
*rgfInOut = dwNethoodAttributes;
else
{
- while (cidl > 0 && *apidl)
- {
- pdump(*apidl);
- SHELL32_GetItemAttributes(this, *apidl, rgfInOut);
- apidl++;
- cidl--;
- }
+ /* FIXME: Implement when enumerating items is implemented */
+#ifdef HACKY_UNC_PATHS
+ *rgfInOut = SFGAO_FILESYSTEM | SFGAO_CANLINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR;
+#endif
}
/* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
HRESULT WINAPI CNetFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
UINT * prgfInOut, LPVOID * ppvOut)
{
- LPITEMIDLIST pidl;
- IUnknown *pObj = NULL;
+ LPVOID pObj = NULL;
HRESULT hr = E_INVALIDARG;
TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
{
- IContextMenu * pCm = NULL;
- hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, 0, NULL, &pCm);
+ IContextMenu * pCm = NULL;
+ HKEY hkey;
+ UINT cKeys = 0;
+ AddClassKeyToArray(L"Folder", &hkey, &cKeys);
+ hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, this, NetFolderMenuCallback, cKeys, &hkey, &pCm);
pObj = pCm;
}
else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1))
hr = IDataObject_Constructor (hwndOwner, pidlRoot, apidl, cidl, &pDo);
pObj = pDo;
}
- else if (IsEqualIID(riid, IID_IExtractIconA) && (cidl == 1))
+ else if ((IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && (cidl == 1))
{
- pidl = ILCombine (pidlRoot, apidl[0]);
- pObj = IExtractIconA_Constructor (pidl);
- SHFree (pidl);
- hr = S_OK;
- }
- else if (IsEqualIID(riid, IID_IExtractIconW) && (cidl == 1))
- {
- pidl = ILCombine (pidlRoot, apidl[0]);
- pObj = IExtractIconW_Constructor (pidl);
- SHFree (pidl);
- hr = S_OK;
+ hr = CNetFolderExtractIcon_CreateInstance(apidl[0], riid, &pObj);
}
else if (IsEqualIID(riid, IID_IDropTarget) && (cidl >= 1))
{
*/
HRESULT WINAPI CNetFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{
- FIXME("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
- pdump(pidl);
-
- if (!strRet)
+ if (!strRet || !pidl || !pidl->mkid.cb)
return E_INVALIDARG;
+#ifdef HACKY_UNC_PATHS
+ return SHSetStrRet(strRet, (LPCWSTR)pidl->mkid.abID);
+#endif
return E_NOTIMPL;
}
HRESULT WINAPI CNetFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
{
- WCHAR buffer[MAX_PATH] = {0};
- HRESULT hr = E_FAIL;
-
if (iColumn >= NETWORKPLACESSHELLVIEWCOLUMNS)
return E_FAIL;
psd->fmt = NetworkPlacesSFHeader[iColumn].fmt;
psd->cxChar = NetworkPlacesSFHeader[iColumn].cxChar;
if (pidl == NULL)
- {
- psd->str.uType = STRRET_WSTR;
- if (LoadStringW(shell32_hInstance, NetworkPlacesSFHeader[iColumn].colnameid, buffer, _countof(buffer)))
- hr = SHStrDupW(buffer, &psd->str.pOleStr);
-
- return hr;
- }
+ return SHSetStrRet(&psd->str, NetworkPlacesSFHeader[iColumn].colnameid);
if (iColumn == COLUMN_NAME)
return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
*/
HRESULT WINAPI CNetFolder::Initialize(LPCITEMIDLIST pidl)
{
- TRACE("(%p)->(%p)\n", this, pidl);
+ if (pidlRoot)
+ SHFree((LPVOID)pidlRoot);
- return E_NOTIMPL;
+ pidlRoot = ILClone(pidl);
+ return S_OK;
}
/**************************************************************************
* CNetFolder::GetCurFolder
*/
-HRESULT WINAPI CNetFolder::GetCurFolder(LPITEMIDLIST *pidl)
+HRESULT WINAPI CNetFolder::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
{
TRACE("(%p)->(%p)\n", this, pidl);