[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / folders / CNetFolder.cpp
index fe72098..f34b92a 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,120 @@ 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);
+                    /* Sounds like a WTF hack.... Is Wine doing correct? */
+                    if (!wcscmp(lpCur->lpRemoteName, lpCur->lpProvider))
+                    {
+                        lpCur->lpRemoteName = NULL;
+                    }
+                    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 +216,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 +256,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 +264,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);
+    }
 
-    return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
+#else
+    return E_NOTIMPL;
+#endif
 }
 
 /**************************************************************************
@@ -127,12 +318,7 @@ HRESULT WINAPI CNetFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserv
 
 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;
 }
 
 /**************************************************************************
@@ -163,11 +349,7 @@ HRESULT WINAPI CNetFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID
     }
     else if (IsEqualIID(riid, IID_IShellView))
     {
-        hr = IShellView_Constructor((IShellFolder *)this, &pShellView);
-        if (pShellView)
-        {
-            hr = pShellView->QueryInterface(riid, ppvOut);
-        }
+        hr = CDefView_Constructor(this, riid, ppvOut);
     }
     TRACE("-- (%p)->(interface=%p)\n", this, ppvOut);
     return hr;
@@ -198,13 +380,10 @@ HRESULT WINAPI CNetFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apid
         *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 */
@@ -290,12 +469,44 @@ HRESULT WINAPI CNetFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH
 */
 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);
+    LPWSTR pszName;
+
+    TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl, dwFlags, strRet);
+    pdump (pidl);
 
     if (!strRet)
         return E_INVALIDARG;
 
+    if (!pidl->mkid.cb)
+    {
+        pszName = (LPWSTR)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
+        if (!pszName)
+            return E_OUTOFMEMORY;
+
+        if (LoadStringW(shell32_hInstance, IDS_NETWORKPLACE, pszName, MAX_PATH))
+        {
+            pszName[MAX_PATH-1] = L'\0';
+            strRet->uType = STRRET_WSTR;
+            strRet->pOleStr = pszName;
+            return S_OK;
+        }
+        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;
 }
 
@@ -417,7 +628,7 @@ HRESULT WINAPI CNetFolder::Initialize(LPCITEMIDLIST pidl)
 {
     TRACE("(%p)->(%p)\n", this, pidl);
 
-    return E_NOTIMPL;
+    return S_OK;
 }
 
 /**************************************************************************