[SHELL32] Fix for BuildPathsList, this solves some problems showing while copying...
[reactos.git] / reactos / dll / win32 / shell32 / folders / CRecycleBin.cpp
index 374cd1a..480d3ce 100644 (file)
@@ -63,6 +63,19 @@ static const columninfo RecycleBinColumns[] =
  * Recycle Bin folder
  */
 
+HRESULT CRecyclerExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
+{
+    CComPtr<IDefaultExtractIconInit> initIcon;
+    HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    /* FIXME: This is completely unimplemented */
+    initIcon->SetNormalIcon(swShell32Name, 0);
+
+    return initIcon->QueryInterface(riid, ppvOut);
+}
+
 class CRecycleBinEnum :
     public CEnumIDListBase
 {
@@ -475,7 +488,7 @@ UnpackDetailsFromPidl(LPCITEMIDLIST pidl)
 
 HRESULT WINAPI CRecycleBin::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
 {
-    return ShellObjectCreatorInit<CRecycleBinEnum>(dwFlags, IID_IEnumIDList, ppEnumIDList);
+    return ShellObjectCreatorInit<CRecycleBinEnum>(dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
 }
 
 HRESULT WINAPI CRecycleBin::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbc, REFIID riid, void **ppv)
@@ -492,11 +505,41 @@ HRESULT WINAPI CRecycleBin::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbc, REF
 
 HRESULT WINAPI CRecycleBin::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 {
-    /* TODO */
-    TRACE("(%p, %p, %p, %p)\n", this, (void *)lParam, pidl1, pidl2);
-    if (pidl1->mkid.cb != pidl2->mkid.cb)
-        return MAKE_HRESULT(SEVERITY_SUCCESS, 0, pidl1->mkid.cb - pidl2->mkid.cb);
-    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (unsigned short)memcmp(pidl1->mkid.abID, pidl2->mkid.abID, pidl1->mkid.cb));
+    PIDLRecycleStruct* pData1 = _ILGetRecycleStruct(pidl1);
+    PIDLRecycleStruct* pData2 = _ILGetRecycleStruct(pidl2);
+    LPWSTR pName1, pName2;
+
+    if(!pData1 || !pData2 || LOWORD(lParam) >= COLUMNS_COUNT)
+        return E_INVALIDARG;
+
+    SHORT result;
+    LONGLONG diff;
+    switch (LOWORD(lParam))
+    {
+        case 0: /* Name */
+            pName1 = PathFindFileNameW(pData1->szName);
+            pName2 = PathFindFileNameW(pData2->szName);
+            result = wcsicmp(pName1, pName2);
+            break;
+        case 1: /* Orig. Location */
+            result = wcsicmp(pData1->szName, pData2->szName);
+            break;
+        case 2: /* Date Deleted */
+            result = CompareFileTime(&pData1->DeletionTime, &pData2->DeletionTime);
+            break;
+        case 3: /* Size */
+            diff = pData1->FileSize.QuadPart - pData2->FileSize.QuadPart;
+            return MAKE_COMPARE_HRESULT(diff);
+        case 4: /* Type */
+            pName1 = PathFindExtensionW(pData1->szName);
+            pName2 = PathFindExtensionW(pData2->szName);
+            result = wcsicmp(pName1, pName2);
+            break;
+        case 5: /* Modified */
+            result = CompareFileTime(&pData1->LastModification, &pData2->LastModification);
+            break;
+    }
+    return MAKE_COMPARE_HRESULT(result);
 }
 
 HRESULT WINAPI CRecycleBin::CreateViewObject(HWND hwndOwner, REFIID riid, void **ppv)
@@ -541,7 +584,7 @@ HRESULT WINAPI CRecycleBin::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY api
 HRESULT WINAPI CRecycleBin::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
         REFIID riid, UINT *prgfInOut, void **ppv)
 {
-    IUnknown *pObj = NULL;
+    LPVOID pObj = NULL;
     HRESULT hr = E_INVALIDARG;
 
     TRACE ("(%p)->(%p,%u,apidl=%p, %p %p)\n", this,
@@ -562,21 +605,9 @@ HRESULT WINAPI CRecycleBin::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_C
         hr = QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
         pObj = pDt;
     }
-    else if(IsEqualIID(riid, IID_IExtractIconA) && (cidl == 1))
-    {
-        // FIXME: This is not correct, it does not show the right icons
-        LPITEMIDLIST pidlItem = ILCombine(pidl, apidl[0]);
-        pObj = IExtractIconA_Constructor(pidlItem);
-        SHFree(pidlItem);
-        hr = S_OK;
-    }
-    else if (IsEqualIID(riid, IID_IExtractIconW) && (cidl == 1))
+    else if((IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && (cidl == 1))
     {
-        // FIXME: This is not correct, it does not show the right icons
-        LPITEMIDLIST pidlItem = ILCombine(pidl, apidl[0]);
-        pObj = IExtractIconW_Constructor(pidlItem);
-        SHFree(pidlItem);
-        hr = S_OK;
+        hr = CRecyclerExtractIcon_CreateInstance(apidl[0], riid, &pObj);
     }
     else
         hr = E_NOINTERFACE;
@@ -596,19 +627,6 @@ HRESULT WINAPI CRecycleBin::GetDisplayNameOf(PCUITEMID_CHILD pidl, SHGDNF uFlags
 
     TRACE("(%p, %p, %x, %p)\n", this, pidl, (unsigned int)uFlags, pName);
 
-
-    if (_ILIsBitBucket (pidl))
-    {
-        WCHAR pszPath[100];
-
-        if (HCR_GetClassNameW(CLSID_RecycleBin, pszPath, MAX_PATH))
-        {
-            pName->uType = STRRET_WSTR;
-            pName->pOleStr = StrDupW(pszPath);
-            return S_OK;
-        }
-    }
-
     pFileDetails = _ILGetRecycleStruct(pidl);
     if (!pFileDetails)
     {
@@ -656,8 +674,10 @@ HRESULT WINAPI CRecycleBin::EnumSearches(IEnumExtraSearch **ppEnum)
 HRESULT WINAPI CRecycleBin::GetDefaultColumn(DWORD dwReserved, ULONG *pSort, ULONG *pDisplay)
 {
     TRACE("(%p, %x, %p, %p)\n", this, (unsigned int)dwReserved, pSort, pDisplay);
-    *pSort = 0;
-    *pDisplay = 0;
+    if (pSort)
+        *pSort = 0;
+    if (pDisplay)
+        *pDisplay = 0;
     return S_OK;
 }
 
@@ -710,11 +730,7 @@ HRESULT WINAPI CRecycleBin::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, LPS
     pDetails->fmt = RecycleBinColumns[iColumn].fmt;
     pDetails->cxChar = RecycleBinColumns[iColumn].cxChars;
     if (pidl == NULL)
-    {
-        pDetails->str.uType = STRRET_WSTR;
-        LoadStringW(shell32_hInstance, RecycleBinColumns[iColumn].column_name_id, buffer, MAX_PATH);
-        return SHStrDupW(buffer, &pDetails->str.pOleStr);
-    }
+        return SHSetStrRet(&pDetails->str, RecycleBinColumns[iColumn].column_name_id);
 
     if (iColumn == COLUMN_NAME)
         return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str);
@@ -738,6 +754,7 @@ HRESULT WINAPI CRecycleBin::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, LPS
             FormatDateTime(buffer, MAX_PATH, &pFileDetails->LastModification);
             break;
         case COLUMN_TYPE:
+            // FIXME: We should in fact use a UNICODE version of _ILGetFileType
             szTypeName[0] = L'\0';
             wcscpy(buffer, PathFindExtensionW(pFileDetails->szName));
             if (!( HCR_MapTypeToValueW(buffer, buffer, sizeof(buffer) / sizeof(WCHAR), TRUE) &&
@@ -749,15 +766,12 @@ HRESULT WINAPI CRecycleBin::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, LPS
                 if (LoadStringW(shell32_hInstance, IDS_SHV_COLUMN1, &szTypeName[Length], (sizeof(szTypeName) / sizeof(WCHAR)) - Length))
                     szTypeName[(sizeof(szTypeName)/sizeof(WCHAR))-1] = L'\0';
             }
-            pDetails->str.uType = STRRET_WSTR;
-            return SHStrDupW(szTypeName, &pDetails->str.pOleStr);
-            break;
+            return SHSetStrRet(&pDetails->str, szTypeName);
         default:
             return E_FAIL;
     }
 
-    pDetails->str.uType = STRRET_WSTR;
-    return SHStrDupW(buffer, &pDetails->str.pOleStr);
+    return SHSetStrRet(&pDetails->str, buffer);
 }
 
 HRESULT WINAPI CRecycleBin::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
@@ -770,6 +784,17 @@ HRESULT WINAPI CRecycleBin::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
     return S_OK;
 }
 
+BOOL CRecycleBin::RecycleBinIsEmpty()
+{
+    CComPtr<IEnumIDList> spEnumFiles;
+    HRESULT hr = EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &spEnumFiles);
+    if (FAILED(hr))
+        return TRUE;
+    CComHeapPtr<ITEMIDLIST> spPidl;
+    ULONG itemcount;
+    return spEnumFiles->Next(1, &spPidl, &itemcount) != S_OK;
+    }
+
 /*************************************************************************
  * RecycleBin IContextMenu interface
  */
@@ -788,7 +813,7 @@ HRESULT WINAPI CRecycleBin::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT i
     memset(&mii, 0, sizeof(mii));
     mii.cbSize = sizeof(mii);
     mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
-    mii.fState = MFS_ENABLED;
+    mii.fState = RecycleBinIsEmpty() ? MFS_DISABLED : MFS_ENABLED;
     szBuffer[0] = L'\0';
     LoadStringW(shell32_hInstance, IDS_EMPTY_BITBUCKET, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
     mii.dwTypeData = szBuffer;
@@ -1137,7 +1162,7 @@ HRESULT WINAPI DoDeleteDataObject(IDataObject *pda, DWORD fMask)
     *pwszFilename = L'\0';
 
     /* Build paths list */
-    LPWSTR pwszPaths = BuildPathsList(wszPath, lpcida->cidl, (LPCITEMIDLIST*) apidl);
+    LPWSTR pwszPaths = BuildPathsList(wszPath, lpcida->cidl, (LPCITEMIDLIST*) apidl, FALSE);
     if (!pwszPaths)
     {
         SHFree(pidl);