[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / folders / CNetFolder.cpp
index d0c04ad..6b3ceae 100644 (file)
 
 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
 */
 
+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},
@@ -43,6 +76,115 @@ static shvheader NetworkPlacesSFHeader[] = {
 
 #define NETWORKPLACESSHELLVIEWCOLUMNS 4
 
+CNetFolderEnum::CNetFolderEnum()
+{
+}
+
+CNetFolderEnum::~CNetFolderEnum()
+{
+}
+
+HRESULT WINAPI CNetFolderEnum::Initialize(HWND hwndOwner, DWORD dwFlags)
+{
+    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;
@@ -69,6 +211,27 @@ HRESULT WINAPI CNetFolder::ParseDisplayName(HWND hwndOwner, LPBC pbcReserved, LP
         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),
@@ -88,14 +251,7 @@ HRESULT WINAPI CNetFolder::ParseDisplayName(HWND hwndOwner, LPBC pbcReserved, LP
 */
 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_IEnumIDList, ppEnumIDList);
 }
 
 /**************************************************************************
@@ -103,10 +259,40 @@ HRESULT WINAPI CNetFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLI
 */
 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);
+#ifdef HACKY_UNC_PATHS
+    HRESULT hr;
+    CComPtr<IPersistFolder3> ppf3;
+    hr = SHCoCreateInstance(NULL, &CLSID_ShellFSFolder, NULL, IID_PPV_ARG(IPersistFolder3, &ppf3));
+    if (FAILED(hr))
+        return hr;
 
+    PERSIST_FOLDER_TARGET_INFO pfti = {0};
+    pfti.csidl = -1;
+    wcscpy(pfti.szTargetParsingName, (WCHAR*)pidl->mkid.abID);
+
+    PCUIDLIST_RELATIVE pidlChild = ILCloneFirst (pidl);
+
+    hr = ppf3->InitializeEx(NULL, ILCombine(pidlRoot,pidlChild), &pfti);
+    if (FAILED(hr))
+        return hr;
+
+    if (_ILIsPidlSimple (pidl))
+    {
+        return ppf3->QueryInterface(riid, ppvOut);
+    }
+    else
+    {
+        CComPtr<IShellFolder> psf;
+        hr = ppf3->QueryInterface(IID_PPV_ARG(IShellFolder, &psf));
+        if (FAILED(hr))
+            return hr;
+
+        return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut);
+    }
+
+#else
     return E_NOTIMPL;
+#endif
 }
 
 /**************************************************************************
@@ -190,6 +376,9 @@ HRESULT WINAPI CNetFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apid
     else
     {
         /* 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 */
@@ -299,7 +488,20 @@ HRESULT WINAPI CNetFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags,
         CoTaskMemFree(pszName);
         return E_FAIL;
     }
+#ifdef HACKY_UNC_PATHS
+    else
+    {
+        LPCWSTR pstr = (LPCWSTR)pidl->mkid.abID;
+        pszName = (LPWSTR)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
+        if (!pszName)
+            return E_OUTOFMEMORY;
 
+        wcscpy(pszName, pstr);
+        strRet->pOleStr = pszName;
+        strRet->uType = STRRET_WSTR;
+        return S_OK;
+    }
+#endif
     return E_NOTIMPL;
 }
 
@@ -421,7 +623,7 @@ HRESULT WINAPI CNetFolder::Initialize(LPCITEMIDLIST pidl)
 {
     TRACE("(%p)->(%p)\n", this, pidl);
 
-    return E_NOTIMPL;
+    return S_OK;
 }
 
 /**************************************************************************