ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

recyclebin.cpp
Go to the documentation of this file.
00001 /*
00002  * Trash virtual folder support. The trashing engine is implemented in trash.c
00003  *
00004  * Copyright (C) 2006 Mikolaj Zalewski
00005  * Copyright (C) 2009 Andrew Hill
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #define MAX_PROPERTY_SHEET_PAGE 32
00023 
00024 #include <precomp.h>
00025 
00026 WINE_DEFAULT_DEBUG_CHANNEL(CRecycleBin);
00027 
00028 typedef struct
00029 {
00030     int column_name_id;
00031     const GUID *fmtId;
00032     DWORD pid;
00033     int pcsFlags;
00034     int fmt;
00035     int cxChars;
00036 } columninfo;
00037 
00038 static const columninfo RecycleBinColumns[] =
00039 {
00040     {IDS_SHV_COLUMN1,        &FMTID_Storage,   PID_STG_NAME,       SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_LEFT,  30},
00041     {IDS_SHV_COLUMN_DELFROM, &FMTID_Displaced, PID_DISPLACED_FROM, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_LEFT,  30},
00042     {IDS_SHV_COLUMN_DELDATE, &FMTID_Displaced, PID_DISPLACED_DATE, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT,  20},
00043     {IDS_SHV_COLUMN2,        &FMTID_Storage,   PID_STG_SIZE,       SHCOLSTATE_TYPE_INT | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_RIGHT, 20},
00044     {IDS_SHV_COLUMN3,        &FMTID_Storage,   PID_STG_STORAGETYPE, SHCOLSTATE_TYPE_INT | SHCOLSTATE_ONBYDEFAULT,  LVCFMT_LEFT,  20},
00045     {IDS_SHV_COLUMN4,        &FMTID_Storage,   PID_STG_WRITETIME,  SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT,  20},
00046     /*    {"creation time",  &FMTID_Storage,   PID_STG_CREATETIME, SHCOLSTATE_TYPE_DATE,                        LVCFMT_LEFT,  20}, */
00047     /*    {"attribs",        &FMTID_Storage,   PID_STG_ATTRIBUTES, SHCOLSTATE_TYPE_STR,                         LVCFMT_LEFT,  20},       */
00048 };
00049 
00050 #define COLUMN_NAME    0
00051 #define COLUMN_DELFROM 1
00052 #define COLUMN_DATEDEL 2
00053 #define COLUMN_SIZE    3
00054 #define COLUMN_TYPE    4
00055 #define COLUMN_MTIME   5
00056 
00057 #define COLUMNS_COUNT  6
00058 
00059 /*
00060  * Recycle Bin folder
00061  */
00062 
00063 class CRecycleBinEnum :
00064     public IEnumIDListImpl
00065 {
00066     private:
00067     public:
00068         CRecycleBinEnum();
00069         ~CRecycleBinEnum();
00070         HRESULT WINAPI Initialize(DWORD dwFlags);
00071         static BOOL WINAPI CBEnumRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile);
00072         BOOL WINAPI CBEnumRecycleBin(IN HANDLE hDeletedFile);
00073 
00074         BEGIN_COM_MAP(CRecycleBinEnum)
00075         COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
00076         END_COM_MAP()
00077 };
00078 
00079 class CRecycleBinItemContextMenu :
00080     public CComObjectRootEx<CComMultiThreadModelNoCS>,
00081     public IContextMenu2
00082 {
00083     private:
00084         LPITEMIDLIST                        apidl;
00085     public:
00086         CRecycleBinItemContextMenu();
00087         ~CRecycleBinItemContextMenu();
00088         HRESULT WINAPI Initialize(LPCITEMIDLIST pidl);
00089 
00090         // IContextMenu
00091         virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
00092         virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
00093         virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
00094 
00095         // IContextMenu2
00096         virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
00097 
00098         BEGIN_COM_MAP(CRecycleBinItemContextMenu)
00099         COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
00100         COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
00101         END_COM_MAP()
00102 };
00103 
00104 typedef struct
00105 {
00106     PIDLRecycleStruct *pFileDetails;
00107     HANDLE hDeletedFile;
00108     BOOL bFound;
00109 } SEARCH_CONTEXT, *PSEARCH_CONTEXT;
00110 
00111 typedef struct
00112 {
00113     DWORD dwNukeOnDelete;
00114     DWORD dwSerial;
00115     DWORD dwMaxCapacity;
00116 } DRIVE_ITEM_CONTEXT, *PDRIVE_ITEM_CONTEXT;
00117 
00118 BOOL WINAPI CBSearchRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile)
00119 {
00120     PSEARCH_CONTEXT pContext = (PSEARCH_CONTEXT)Context;
00121 
00122     PDELETED_FILE_DETAILS_W pFileDetails;
00123     DWORD dwSize;
00124     BOOL ret;
00125 
00126     if (!GetDeletedFileDetailsW(hDeletedFile,
00127                                 0,
00128                                 NULL,
00129                                 &dwSize) &&
00130             GetLastError() != ERROR_INSUFFICIENT_BUFFER)
00131     {
00132         ERR("GetDeletedFileDetailsW failed\n");
00133         return FALSE;
00134     }
00135 
00136     pFileDetails = (DELETED_FILE_DETAILS_W *)SHAlloc(dwSize);
00137     if (!pFileDetails)
00138     {
00139         ERR("No memory\n");
00140         return FALSE;
00141     }
00142 
00143     if (!GetDeletedFileDetailsW(hDeletedFile,
00144                                 dwSize,
00145                                 pFileDetails,
00146                                 NULL))
00147     {
00148         ERR("GetDeletedFileDetailsW failed\n");
00149         SHFree(pFileDetails);
00150         return FALSE;
00151     }
00152 
00153     ret = memcmp(pFileDetails, pContext->pFileDetails, dwSize);
00154     if (!ret)
00155     {
00156         pContext->hDeletedFile = hDeletedFile;
00157         pContext->bFound = TRUE;
00158     }
00159     else
00160         CloseRecycleBinHandle(hDeletedFile);
00161 
00162     SHFree(pFileDetails);
00163     return ret;
00164 }
00165 
00166 static PIDLRecycleStruct * _ILGetRecycleStruct(LPCITEMIDLIST pidl)
00167 {
00168     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
00169 
00170     if (pdata && pdata->type == 0x00)
00171         return (PIDLRecycleStruct*) & (pdata->u.crecycle);
00172 
00173     return NULL;
00174 }
00175 
00176 CRecycleBinEnum::CRecycleBinEnum()
00177 {
00178 }
00179 
00180 CRecycleBinEnum::~CRecycleBinEnum()
00181 {
00182 }
00183 
00184 HRESULT WINAPI CRecycleBinEnum::Initialize(DWORD dwFlags)
00185 {
00186     static LPCWSTR szDrive = L"C:\\";
00187 
00188     if (dwFlags & SHCONTF_NONFOLDERS)
00189     {
00190         TRACE("Starting Enumeration\n");
00191 
00192         if (!EnumerateRecycleBinW(szDrive /* FIXME */ , CBEnumRecycleBin, (PVOID)this))
00193         {
00194             WARN("Error: EnumerateCRecycleBinW failed\n");
00195             return E_FAIL;
00196         }
00197     }
00198     else
00199     {
00200         // do nothing
00201     }
00202     return S_OK;
00203 }
00204 
00205 static LPITEMIDLIST _ILCreateRecycleItem(PDELETED_FILE_DETAILS_W pFileDetails)
00206 {
00207     PIDLDATA tmp;
00208     LPITEMIDLIST pidl;
00209     PIDLRecycleStruct * p;
00210     int size0 = (char*)&tmp.u.crecycle.szName - (char*)&tmp.u.crecycle;
00211     int size = size0;
00212 
00213     tmp.type = 0x00;
00214     size += (wcslen(pFileDetails->FileName) + 1) * sizeof(WCHAR);
00215 
00216     pidl = (LPITEMIDLIST)SHAlloc(size + 4);
00217     if (!pidl)
00218         return pidl;
00219 
00220     pidl->mkid.cb = size + 2;
00221     memcpy(pidl->mkid.abID, &tmp, 2 + size0);
00222 
00223     p = &((PIDLDATA*)pidl->mkid.abID)->u.crecycle;
00224     RtlCopyMemory(p, pFileDetails, sizeof(DELETED_FILE_DETAILS_W));
00225     wcscpy(p->szName, pFileDetails->FileName);
00226     *(WORD*)((char*)pidl + (size + 2)) = 0;
00227     return pidl;
00228 }
00229 
00230 BOOL WINAPI CRecycleBinEnum::CBEnumRecycleBin(IN PVOID Context, IN HANDLE hDeletedFile)
00231 {
00232     return ((CRecycleBinEnum *)Context)->CBEnumRecycleBin(hDeletedFile);
00233 }
00234 
00235 BOOL WINAPI CRecycleBinEnum::CBEnumRecycleBin(IN HANDLE hDeletedFile)
00236 {
00237     PDELETED_FILE_DETAILS_W pFileDetails;
00238     DWORD dwSize;
00239     LPITEMIDLIST pidl = NULL;
00240     BOOL ret;
00241 
00242     if (!GetDeletedFileDetailsW(hDeletedFile,
00243                                 0,
00244                                 NULL,
00245                                 &dwSize) &&
00246             GetLastError() != ERROR_INSUFFICIENT_BUFFER)
00247     {
00248         ERR("GetDeletedFileDetailsW failed\n");
00249         return FALSE;
00250     }
00251 
00252     pFileDetails = (DELETED_FILE_DETAILS_W *)SHAlloc(dwSize);
00253     if (!pFileDetails)
00254     {
00255         ERR("No memory\n");
00256         return FALSE;
00257     }
00258 
00259     if (!GetDeletedFileDetailsW(hDeletedFile,
00260                                 dwSize,
00261                                 pFileDetails,
00262                                 NULL))
00263     {
00264         ERR("GetDeletedFileDetailsW failed\n");
00265         SHFree(pFileDetails);
00266         return FALSE;
00267     }
00268 
00269     pidl = _ILCreateRecycleItem(pFileDetails);
00270     if (!pidl)
00271     {
00272         SHFree(pFileDetails);
00273         return FALSE;
00274     }
00275 
00276     ret = AddToEnumList(pidl);
00277 
00278     if (!ret)
00279         SHFree(pidl);
00280     SHFree(pFileDetails);
00281     TRACE("Returning %d\n", ret);
00282     CloseRecycleBinHandle(hDeletedFile);
00283     return ret;
00284 }
00285 
00286 /**************************************************************************
00287 * IContextMenu2 Bitbucket Item Implementation
00288 */
00289 
00290 CRecycleBinItemContextMenu::CRecycleBinItemContextMenu()
00291 {
00292     apidl = NULL;
00293 }
00294 
00295 CRecycleBinItemContextMenu::~CRecycleBinItemContextMenu()
00296 {
00297     ILFree(apidl);
00298 }
00299 
00300 HRESULT WINAPI CRecycleBinItemContextMenu::Initialize(LPCITEMIDLIST pidl)
00301 {
00302     apidl = ILClone(pidl);
00303     if (apidl == NULL)
00304         return E_OUTOFMEMORY;
00305     return S_OK;
00306 }
00307 
00308 HRESULT WINAPI CRecycleBinItemContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
00309 {
00310     WCHAR szBuffer[30] = {0};
00311     ULONG Count = 1;
00312 
00313     TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
00314 
00315     if (LoadStringW(shell32_hInstance, IDS_RESTORE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
00316     {
00317         szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
00318         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED);
00319         Count++;
00320     }
00321 
00322     if (LoadStringW(shell32_hInstance, IDS_CUT, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
00323     {
00324         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
00325         szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
00326         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
00327     }
00328 
00329     if (LoadStringW(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
00330     {
00331         szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
00332         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
00333         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
00334     }
00335 
00336     if (LoadStringW(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
00337     {
00338         szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
00339         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
00340         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT);
00341     }
00342 
00343     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
00344 }
00345 
00346 HRESULT WINAPI CRecycleBinItemContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
00347 {
00348     SEARCH_CONTEXT Context;
00349     static LPCWSTR szDrive = L"C:\\";
00350 
00351     TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
00352 
00353     if (lpcmi->lpVerb == MAKEINTRESOURCEA(1) || lpcmi->lpVerb == MAKEINTRESOURCEA(5))
00354     {
00355         Context.pFileDetails = _ILGetRecycleStruct(apidl);
00356         Context.bFound = FALSE;
00357 
00358         EnumerateRecycleBinW(szDrive, CBSearchRecycleBin, (PVOID)&Context);
00359         if (!Context.bFound)
00360             return E_FAIL;
00361 
00362         if (lpcmi->lpVerb == MAKEINTRESOURCEA(1))
00363         {
00364             /* restore file */
00365             if (RestoreFile(Context.hDeletedFile))
00366                 return S_OK;
00367             else
00368                 return E_FAIL;
00369         }
00370         else
00371         {
00372             DeleteFileHandleToRecycleBin(Context.hDeletedFile);
00373             return E_NOTIMPL;
00374         }
00375     }
00376     else if (lpcmi->lpVerb == MAKEINTRESOURCEA(3))
00377     {
00378         FIXME("implement cut\n");
00379         return E_NOTIMPL;
00380     }
00381     else if (lpcmi->lpVerb == MAKEINTRESOURCEA(7))
00382     {
00383         FIXME("implement properties\n");
00384         return E_NOTIMPL;
00385     }
00386 
00387     return S_OK;
00388 }
00389 
00390 HRESULT WINAPI CRecycleBinItemContextMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
00391 {
00392     TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
00393 
00394     return E_FAIL;
00395 }
00396 
00397 HRESULT WINAPI CRecycleBinItemContextMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
00398 {
00399     TRACE("CRecycleBin_IContextMenu2Item_HandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
00400 
00401     return E_NOTIMPL;
00402 }
00403 
00404 static HRESULT WINAPI CRecycleBinItemContextMenuConstructor(REFIID riid, LPCITEMIDLIST pidl, LPVOID *ppv)
00405 {
00406     CComObject<CRecycleBinItemContextMenu>    *theMenu;
00407     CComPtr<IUnknown>                        result;
00408     HRESULT                                    hResult;
00409 
00410     TRACE("%s\n", shdebugstr_guid(&riid));
00411 
00412     if (ppv == NULL)
00413         return E_POINTER;
00414     *ppv = NULL;
00415     ATLTRY(theMenu = new CComObject<CRecycleBinItemContextMenu>);
00416     if (theMenu == NULL)
00417         return E_OUTOFMEMORY;
00418     hResult = theMenu->QueryInterface(riid, (void **)&result);
00419     if (FAILED(hResult))
00420     {
00421         delete theMenu;
00422         return hResult;
00423     }
00424     hResult = theMenu->Initialize(pidl);
00425     if (FAILED(hResult))
00426         return hResult;
00427     *ppv = result.Detach();
00428     TRACE ("--(%p)\n", *ppv);
00429     return S_OK;
00430 }
00431 
00432 CRecycleBin::CRecycleBin()
00433 {
00434     pidl = NULL;
00435     iIdEmpty = 0;
00436 }
00437 
00438 CRecycleBin::~CRecycleBin()
00439 {
00440     /*    InterlockedDecrement(&objCount);*/
00441     SHFree(pidl);
00442 }
00443 
00444 /*************************************************************************
00445  * RecycleBin IPersistFolder2 interface
00446  */
00447 
00448 HRESULT WINAPI CRecycleBin::GetClassID(CLSID *pClassID)
00449 {
00450     TRACE("(%p, %p)\n", this, pClassID);
00451     if (pClassID == NULL)
00452         return E_INVALIDARG;
00453     memcpy(pClassID, &CLSID_RecycleBin, sizeof(CLSID));
00454     return S_OK;
00455 }
00456 
00457 HRESULT WINAPI CRecycleBin::Initialize(LPCITEMIDLIST pidl)
00458 {
00459     TRACE("(%p, %p)\n", this, pidl);
00460 
00461     SHFree((LPVOID)this->pidl);
00462     this->pidl = ILClone(pidl);
00463     if (this->pidl == NULL)
00464         return E_OUTOFMEMORY;
00465     return S_OK;
00466 }
00467 
00468 HRESULT WINAPI CRecycleBin::GetCurFolder(LPITEMIDLIST *ppidl)
00469 {
00470     TRACE("\n");
00471     *ppidl = ILClone(pidl);
00472     return S_OK;
00473 }
00474 
00475 /*************************************************************************
00476  * RecycleBin IShellFolder2 interface
00477  */
00478 
00479 HRESULT WINAPI CRecycleBin::ParseDisplayName(HWND hwnd, LPBC pbc,
00480         LPOLESTR pszDisplayName, ULONG *pchEaten, LPITEMIDLIST *ppidl,
00481         ULONG *pdwAttributes)
00482 {
00483     FIXME("stub\n");
00484     return E_NOTIMPL;
00485 }
00486 
00487 
00488 PDELETED_FILE_DETAILS_W
00489 UnpackDetailsFromPidl(LPCITEMIDLIST pidl)
00490 {
00491     return (PDELETED_FILE_DETAILS_W)&pidl->mkid.abID;
00492 }
00493 
00494 HRESULT WINAPI CRecycleBin::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
00495 {
00496     CComObject<CRecycleBinEnum>                *theEnumerator;
00497     CComPtr<IEnumIDList>                    result;
00498     HRESULT                                    hResult;
00499 
00500     TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
00501 
00502     if (ppEnumIDList == NULL)
00503         return E_POINTER;
00504     *ppEnumIDList = NULL;
00505     ATLTRY (theEnumerator = new CComObject<CRecycleBinEnum>);
00506     if (theEnumerator == NULL)
00507         return E_OUTOFMEMORY;
00508     hResult = theEnumerator->QueryInterface(IID_IEnumIDList, (void **)&result);
00509     if (FAILED (hResult))
00510     {
00511         delete theEnumerator;
00512         return hResult;
00513     }
00514     hResult = theEnumerator->Initialize(dwFlags);
00515     if (FAILED (hResult))
00516         return hResult;
00517     *ppEnumIDList = result.Detach();
00518 
00519     TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
00520 
00521     return S_OK;
00522 }
00523 
00524 HRESULT WINAPI CRecycleBin::BindToObject(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv)
00525 {
00526     FIXME("(%p, %p, %p, %s, %p) - stub\n", this, pidl, pbc, debugstr_guid(&riid), ppv);
00527     return E_NOTIMPL;
00528 }
00529 
00530 HRESULT WINAPI CRecycleBin::BindToStorage(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppv)
00531 {
00532     FIXME("(%p, %p, %p, %s, %p) - stub\n", this, pidl, pbc, debugstr_guid(&riid), ppv);
00533     return E_NOTIMPL;
00534 }
00535 
00536 HRESULT WINAPI CRecycleBin::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
00537 {
00538     /* TODO */
00539     TRACE("(%p, %p, %p, %p)\n", this, (void *)lParam, pidl1, pidl2);
00540     if (pidl1->mkid.cb != pidl2->mkid.cb)
00541         return MAKE_HRESULT(SEVERITY_SUCCESS, 0, pidl1->mkid.cb - pidl2->mkid.cb);
00542     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (unsigned short)memcmp(pidl1->mkid.abID, pidl2->mkid.abID, pidl1->mkid.cb));
00543 }
00544 
00545 HRESULT WINAPI CRecycleBin::CreateViewObject(HWND hwndOwner, REFIID riid, void **ppv)
00546 {
00547     LPSHELLVIEW pShellView;
00548     HRESULT hr = E_NOINTERFACE;
00549 
00550     TRACE("(%p, %p, %s, %p)\n", this, hwndOwner, debugstr_guid(&riid), ppv);
00551 
00552     if (!ppv)
00553         return hr;
00554 
00555     *ppv = NULL;
00556 
00557     if (IsEqualIID (riid, IID_IDropTarget))
00558     {
00559         WARN ("IDropTarget not implemented\n");
00560         hr = E_NOTIMPL;
00561     }
00562     else if (IsEqualIID (riid, IID_IContextMenu) || IsEqualIID (riid, IID_IContextMenu2))
00563     {
00564         hr = this->QueryInterface(riid, ppv);
00565     }
00566     else if (IsEqualIID (riid, IID_IShellView))
00567     {
00568         hr = IShellView_Constructor ((IShellFolder *)this, &pShellView);
00569         if (pShellView)
00570         {
00571             hr = pShellView->QueryInterface(riid, ppv);
00572             pShellView->Release();
00573         }
00574     }
00575     else
00576         return hr;
00577     TRACE ("-- (%p)->(interface=%p)\n", this, ppv);
00578     return hr;
00579 
00580 }
00581 
00582 HRESULT WINAPI CRecycleBin::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl,
00583         SFGAOF *rgfInOut)
00584 {
00585     TRACE("(%p, %d, {%p, ...}, {%x})\n", this, cidl, apidl ? apidl[0] : NULL, (unsigned int)*rgfInOut);
00586     *rgfInOut &= SFGAO_FOLDER|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANLINK;
00587     return S_OK;
00588 }
00589 
00590 HRESULT WINAPI CRecycleBin::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl,
00591         REFIID riid, UINT *prgfInOut, void **ppv)
00592 {
00593     IUnknown *pObj = NULL;
00594     HRESULT hr = E_INVALIDARG;
00595 
00596     TRACE ("(%p)->(%p,%u,apidl=%p, %p %p)\n", this,
00597            hwndOwner, cidl, apidl, prgfInOut, ppv);
00598 
00599     if (!ppv)
00600         return hr;
00601 
00602     *ppv = NULL;
00603 
00604     if ((IsEqualIID (riid, IID_IContextMenu) || IsEqualIID(riid, IID_IContextMenu2)) && (cidl >= 1))
00605     {
00606         hr = CRecycleBinItemContextMenuConstructor(riid, apidl[0], (void **)&pObj);
00607     }
00608     else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
00609     {
00610         hr = this->QueryInterface(IID_IDropTarget, (LPVOID *) & pObj);
00611     }
00612     else
00613         hr = E_NOINTERFACE;
00614 
00615     if (SUCCEEDED(hr) && !pObj)
00616         hr = E_OUTOFMEMORY;
00617 
00618     *ppv = pObj;
00619     TRACE ("(%p)->hr=0x%08x\n", this, hr);
00620     return hr;
00621 }
00622 
00623 HRESULT WINAPI CRecycleBin::GetDisplayNameOf(LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET *pName)
00624 {
00625     PIDLRecycleStruct *pFileDetails;
00626     LPWSTR pFileName;
00627 
00628     TRACE("(%p, %p, %x, %p)\n", this, pidl, (unsigned int)uFlags, pName);
00629 
00630 
00631     if (_ILIsBitBucket (pidl))
00632     {
00633         WCHAR pszPath[100];
00634 
00635         if (HCR_GetClassNameW(CLSID_RecycleBin, pszPath, MAX_PATH))
00636         {
00637             pName->uType = STRRET_WSTR;
00638             pName->pOleStr = StrDupW(pszPath);
00639             return S_OK;
00640         }
00641     }
00642 
00643     pFileDetails = _ILGetRecycleStruct(pidl);
00644     if (!pFileDetails)
00645     {
00646         pName->cStr[0] = 0;
00647         pName->uType = STRRET_CSTR;
00648         return E_INVALIDARG;
00649     }
00650 
00651     pFileName = wcsrchr(pFileDetails->szName, L'\\');
00652     if (!pFileName)
00653     {
00654         pName->cStr[0] = 0;
00655         pName->uType = STRRET_CSTR;
00656         return E_UNEXPECTED;
00657     }
00658 
00659     pName->pOleStr = StrDupW(pFileName + 1);
00660     if (pName->pOleStr == NULL)
00661         return E_OUTOFMEMORY;
00662 
00663     pName->uType = STRRET_WSTR;
00664     return S_OK;
00665 }
00666 
00667 HRESULT WINAPI CRecycleBin::SetNameOf(HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR pszName,
00668                                       SHGDNF uFlags, LPITEMIDLIST *ppidlOut)
00669 {
00670     TRACE("\n");
00671     return E_FAIL; /* not supported */
00672 }
00673 
00674 HRESULT WINAPI CRecycleBin::GetDefaultSearchGUID(GUID *pguid)
00675 {
00676     FIXME("stub\n");
00677     return E_NOTIMPL;
00678 }
00679 
00680 HRESULT WINAPI CRecycleBin::EnumSearches(IEnumExtraSearch **ppEnum)
00681 {
00682     FIXME("stub\n");
00683     *ppEnum = NULL;
00684     return E_NOTIMPL;
00685 }
00686 
00687 HRESULT WINAPI CRecycleBin::GetDefaultColumn(DWORD dwReserved, ULONG *pSort, ULONG *pDisplay)
00688 {
00689     TRACE("(%p, %x, %p, %p)\n", this, (unsigned int)dwReserved, pSort, pDisplay);
00690     *pSort = 0;
00691     *pDisplay = 0;
00692     return S_OK;
00693 }
00694 
00695 HRESULT WINAPI CRecycleBin::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags)
00696 {
00697     TRACE("(%p, %d, %p)\n", this, iColumn, pcsFlags);
00698     if (iColumn >= COLUMNS_COUNT)
00699         return E_INVALIDARG;
00700     *pcsFlags = RecycleBinColumns[iColumn].pcsFlags;
00701     return S_OK;
00702 }
00703 
00704 HRESULT WINAPI CRecycleBin::GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
00705 {
00706     FIXME("stub\n");
00707     return E_NOTIMPL;
00708 }
00709 
00710 static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME * ft)
00711 {
00712     FILETIME lft;
00713     SYSTEMTIME time;
00714     int ret;
00715 
00716     FileTimeToLocalFileTime(ft, &lft);
00717     FileTimeToSystemTime(&lft, &time);
00718 
00719     ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, buffer, size);
00720     if (ret > 0 && ret < size)
00721     {
00722         /* Append space + time without seconds */
00723         buffer[ret-1] = ' ';
00724         GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &buffer[ret], size - ret);
00725     }
00726 
00727     return (ret != 0 ? E_FAIL : S_OK);
00728 }
00729 
00730 HRESULT WINAPI CRecycleBin::GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, LPSHELLDETAILS pDetails)
00731 {
00732     PIDLRecycleStruct * pFileDetails;
00733     WCHAR buffer[MAX_PATH];
00734     WCHAR szTypeName[100];
00735     LPWSTR pszBackslash;
00736     UINT Length;
00737 
00738     TRACE("(%p, %p, %d, %p)\n", this, pidl, iColumn, pDetails);
00739     if (iColumn >= COLUMNS_COUNT)
00740         return E_FAIL;
00741     pDetails->fmt = RecycleBinColumns[iColumn].fmt;
00742     pDetails->cxChar = RecycleBinColumns[iColumn].cxChars;
00743     if (pidl == NULL)
00744     {
00745         pDetails->str.uType = STRRET_WSTR;
00746         LoadStringW(shell32_hInstance, RecycleBinColumns[iColumn].column_name_id, buffer, MAX_PATH);
00747         return SHStrDupW(buffer, &pDetails->str.pOleStr);
00748     }
00749 
00750     if (iColumn == COLUMN_NAME)
00751         return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str);
00752 
00753     pFileDetails = _ILGetRecycleStruct(pidl);
00754     switch (iColumn)
00755     {
00756         case COLUMN_DATEDEL:
00757             FormatDateTime(buffer, MAX_PATH, &pFileDetails->DeletionTime);
00758             break;
00759         case COLUMN_DELFROM:
00760             pszBackslash = wcsrchr(pFileDetails->szName, L'\\');
00761             Length = (pszBackslash - pFileDetails->szName);
00762             memcpy((LPVOID)buffer, pFileDetails->szName, Length * sizeof(WCHAR));
00763             buffer[Length] = L'\0';
00764             break;
00765         case COLUMN_SIZE:
00766             StrFormatKBSizeW(pFileDetails->FileSize.QuadPart, buffer, MAX_PATH);
00767             break;
00768         case COLUMN_MTIME:
00769             FormatDateTime(buffer, MAX_PATH, &pFileDetails->LastModification);
00770             break;
00771         case COLUMN_TYPE:
00772             szTypeName[0] = L'\0';
00773             wcscpy(buffer, PathFindExtensionW(pFileDetails->szName));
00774             if (!( HCR_MapTypeToValueW(buffer, buffer, sizeof(buffer) / sizeof(WCHAR), TRUE) &&
00775                     HCR_MapTypeToValueW(buffer, szTypeName, sizeof(szTypeName) / sizeof(WCHAR), FALSE )))
00776             {
00777                 wcscpy (szTypeName, PathFindExtensionW(pFileDetails->szName));
00778                 wcscat(szTypeName, L"-");
00779                 Length = wcslen(szTypeName);
00780                 if (LoadStringW(shell32_hInstance, IDS_SHV_COLUMN1, &szTypeName[Length], (sizeof(szTypeName) / sizeof(WCHAR)) - Length))
00781                     szTypeName[(sizeof(szTypeName)/sizeof(WCHAR))-1] = L'\0';
00782             }
00783             pDetails->str.uType = STRRET_WSTR;
00784             return SHStrDupW(szTypeName, &pDetails->str.pOleStr);
00785             break;
00786         default:
00787             return E_FAIL;
00788     }
00789 
00790     pDetails->str.uType = STRRET_WSTR;
00791     return SHStrDupW(buffer, &pDetails->str.pOleStr);
00792 }
00793 
00794 HRESULT WINAPI CRecycleBin::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
00795 {
00796     TRACE("(%p, %d, %p)\n", this, iColumn, pscid);
00797     if (iColumn >= COLUMNS_COUNT)
00798         return E_INVALIDARG;
00799     pscid->fmtid = *RecycleBinColumns[iColumn].fmtId;
00800     pscid->pid = RecycleBinColumns[iColumn].pid;
00801     return S_OK;
00802 }
00803 
00804 /*************************************************************************
00805  * RecycleBin IContextMenu interface
00806  */
00807 
00808 HRESULT WINAPI CRecycleBin::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
00809 {
00810     WCHAR szBuffer[100];
00811     MENUITEMINFOW mii;
00812     int id = 1;
00813 
00814     TRACE("QueryContextMenu %p %p %u %u %u %u\n", this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags );
00815 
00816     if (!hMenu)
00817         return E_INVALIDARG;
00818 
00819     memset(&mii, 0, sizeof(mii));
00820     mii.cbSize = sizeof(mii);
00821     mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
00822     mii.fState = MFS_ENABLED;
00823     szBuffer[0] = L'\0';
00824     LoadStringW(shell32_hInstance, IDS_EMPTY_BITBUCKET, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
00825     mii.dwTypeData = szBuffer;
00826     mii.cch = wcslen(mii.dwTypeData);
00827     mii.wID = idCmdFirst + id++;
00828     mii.fType = MFT_STRING;
00829     iIdEmpty = 1;
00830 
00831     if (!InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
00832         return E_FAIL;
00833 
00834     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, id);
00835 }
00836 
00837 HRESULT WINAPI CRecycleBin::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
00838 {
00839     HRESULT hr;
00840     LPSHELLBROWSER lpSB;
00841     LPSHELLVIEW lpSV = NULL;
00842 
00843     TRACE("%p %p verb %p\n", this, lpcmi, lpcmi->lpVerb);
00844 
00845     if (LOWORD(lpcmi->lpVerb) == iIdEmpty)
00846     {
00847         // FIXME
00848         // path & flags
00849         hr = SHEmptyRecycleBinW(lpcmi->hwnd, L"C:\\", 0);
00850         TRACE("result %x\n", hr);
00851         if (hr != S_OK)
00852             return hr;
00853 
00854         lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
00855         if (lpSB && SUCCEEDED(lpSB->QueryActiveShellView(&lpSV)))
00856             lpSV->Refresh();
00857     }
00858     return S_OK;
00859 }
00860 
00861 HRESULT WINAPI CRecycleBin::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
00862 {
00863     FIXME("%p %lu %u %p %p %u\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
00864 
00865     return E_NOTIMPL;
00866 }
00867 
00868 /*************************************************************************
00869  * RecycleBin IShellPropSheetExt interface
00870  */
00871 
00872 HRESULT WINAPI CRecycleBin::AddPages(LPFNSVADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
00873 {
00874     FIXME("%p %p %lu\n", this, pfnAddPage, lParam);
00875 
00876     return E_NOTIMPL;
00877 }
00878 
00879 HRESULT WINAPI CRecycleBin::ReplacePage(EXPPS uPageID, LPFNSVADDPROPSHEETPAGE pfnReplaceWith, LPARAM lParam)
00880 {
00881     FIXME("%p %lu %p %lu\n", this, uPageID, pfnReplaceWith, lParam);
00882 
00883     return E_NOTIMPL;
00884 }
00885 
00886 /*************************************************************************
00887  * RecycleBin IShellExtInit interface
00888  */
00889 
00890 HRESULT WINAPI CRecycleBin::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
00891 {
00892     TRACE("%p %p %p %p\n", this, pidlFolder, pdtobj, hkeyProgID );
00893     return S_OK;
00894 }
00895 
00896 void toggleNukeOnDeleteOption(HWND hwndDlg, BOOL bEnable)
00897 {
00898     if (bEnable)
00899     {
00900         SendDlgItemMessage(hwndDlg, 14001, BM_SETCHECK, BST_UNCHECKED, 0);
00901         EnableWindow(GetDlgItem(hwndDlg, 14002), FALSE);
00902         SendDlgItemMessage(hwndDlg, 14003, BM_SETCHECK, BST_CHECKED, 0);
00903     }
00904     else
00905     {
00906         SendDlgItemMessage(hwndDlg, 14001, BM_SETCHECK, BST_CHECKED, 0);
00907         EnableWindow(GetDlgItem(hwndDlg, 14002), TRUE);
00908         SendDlgItemMessage(hwndDlg, 14003, BM_SETCHECK, BST_UNCHECKED, 0);
00909     }
00910 }
00911 
00912 
00913 static VOID
00914 InitializeRecycleBinDlg(HWND hwndDlg, WCHAR DefaultDrive)
00915 {
00916     WCHAR CurDrive = L'A';
00917     WCHAR szDrive[] = L"A:\\";
00918     DWORD dwDrives;
00919     WCHAR szName[100];
00920     WCHAR szVolume[100];
00921     DWORD MaxComponent, Flags;
00922     DWORD dwSerial;
00923     LVCOLUMNW lc;
00924     HWND hDlgCtrl;
00925     LVITEMW li;
00926     INT itemCount;
00927     ULARGE_INTEGER TotalNumberOfFreeBytes, TotalNumberOfBytes, FreeBytesAvailable;
00928     RECT rect;
00929     int columnSize;
00930     int defIndex = 0;
00931     DWORD dwSize;
00932     PDRIVE_ITEM_CONTEXT pItem = NULL, pDefault = NULL, pFirst = NULL;
00933 
00934     hDlgCtrl = GetDlgItem(hwndDlg, 14000);
00935 
00936     if (!LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_LOCATION, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
00937         szVolume[0] = 0;
00938 
00939     GetClientRect(hDlgCtrl, &rect);
00940 
00941     memset(&lc, 0, sizeof(LV_COLUMN) );
00942     lc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
00943 
00944     columnSize = 140; //FIXME
00945     lc.iSubItem   = 0;
00946     lc.fmt = LVCFMT_FIXED_WIDTH;
00947     lc.cx         = columnSize;
00948     lc.cchTextMax = wcslen(szVolume);
00949     lc.pszText    = szVolume;
00950     (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&lc);
00951 
00952     if (!LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_DISKSPACE, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
00953         szVolume[0] = 0;
00954 
00955     lc.iSubItem   = 1;
00956     lc.cx         = rect.right - rect.left - columnSize;
00957     lc.cchTextMax = wcslen(szVolume);
00958     lc.pszText    = szVolume;
00959     (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&lc);
00960 
00961     dwDrives = GetLogicalDrives();
00962     itemCount = 0;
00963     do
00964     {
00965         if ((dwDrives & 0x1))
00966         {
00967             UINT Type = GetDriveTypeW(szDrive);
00968             if (Type == DRIVE_FIXED) //FIXME
00969             {
00970                 if (!GetVolumeInformationW(szDrive, szName, sizeof(szName) / sizeof(WCHAR), &dwSerial, &MaxComponent, &Flags, NULL, 0))
00971                 {
00972                     szName[0] = 0;
00973                     dwSerial = -1;
00974                 }
00975 
00976                 swprintf(szVolume, L"%s (%c)", szName, szDrive[0]);
00977                 memset(&li, 0x0, sizeof(LVITEMW));
00978                 li.mask = LVIF_TEXT | LVIF_PARAM;
00979                 li.iSubItem = 0;
00980                 li.pszText = szVolume;
00981                 li.iItem = itemCount;
00982                 SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
00983                 if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable , &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
00984                 {
00985                     if (StrFormatByteSizeW(TotalNumberOfFreeBytes.QuadPart, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
00986                     {
00987 
00988                         pItem = (DRIVE_ITEM_CONTEXT *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DRIVE_ITEM_CONTEXT));
00989                         if (pItem)
00990                         {
00991                             swprintf(szName, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\%04X-%04X", LOWORD(dwSerial), HIWORD(dwSerial));
00992                             dwSize = sizeof(DWORD);
00993                             RegGetValueW(HKEY_CURRENT_USER, szName, L"MaxCapacity", RRF_RT_DWORD, NULL, &pItem->dwMaxCapacity, &dwSize);
00994                             dwSize = sizeof(DWORD);
00995                             RegGetValueW(HKEY_CURRENT_USER, szName, L"NukeOnDelete", RRF_RT_DWORD, NULL, &pItem->dwNukeOnDelete, &dwSize);
00996                             pItem->dwSerial = dwSerial;
00997                             li.mask = LVIF_PARAM;
00998                             li.lParam = (LPARAM)pItem;
00999                             (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
01000                             if (CurDrive == DefaultDrive)
01001                             {
01002                                 defIndex = itemCount;
01003                                 pDefault = pItem;
01004                             }
01005                         }
01006                         if (!pFirst)
01007                             pFirst = pItem;
01008 
01009                         li.mask = LVIF_TEXT;
01010                         li.iSubItem = 1;
01011                         li.pszText = szVolume;
01012                         li.iItem = itemCount;
01013                         (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
01014                     }
01015                 }
01016                 itemCount++;
01017             }
01018         }
01019         CurDrive++;
01020         szDrive[0] = CurDrive;
01021         dwDrives = (dwDrives >> 1);
01022     } while(dwDrives);
01023 
01024     if (!pDefault)
01025         pDefault = pFirst;
01026     if (pDefault)
01027     {
01028         toggleNukeOnDeleteOption(hwndDlg, pDefault->dwNukeOnDelete);
01029         SetDlgItemInt(hwndDlg, 14002, pDefault->dwMaxCapacity, FALSE);
01030     }
01031     ZeroMemory(&li, sizeof(li));
01032     li.mask = LVIF_STATE;
01033     li.stateMask = (UINT) - 1;
01034     li.state = LVIS_FOCUSED | LVIS_SELECTED;
01035     li.iItem = defIndex;
01036     (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
01037 
01038 }
01039 
01040 static BOOL StoreDriveSettings(HWND hwndDlg)
01041 {
01042     int iCount, iIndex;
01043     HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000);
01044     LVITEMW li;
01045     PDRIVE_ITEM_CONTEXT pItem;
01046     HKEY hKey, hSubKey;
01047     WCHAR szSerial[20];
01048     DWORD dwSize;
01049 
01050 
01051     if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume", 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
01052         return FALSE;
01053 
01054     iCount = ListView_GetItemCount(hDlgCtrl);
01055 
01056     ZeroMemory(&li, sizeof(li));
01057     li.mask = LVIF_PARAM;
01058 
01059     for(iIndex = 0; iIndex < iCount; iIndex++)
01060     {
01061         li.iItem = iIndex;
01062         if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&li))
01063         {
01064             pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
01065             swprintf(szSerial, L"%04X-%04X", LOWORD(pItem->dwSerial), HIWORD(pItem->dwSerial));
01066             if (RegCreateKeyExW(hKey, szSerial, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
01067             {
01068                 dwSize = sizeof(DWORD);
01069                 RegSetValueExW(hSubKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&pItem->dwNukeOnDelete, dwSize);
01070                 dwSize = sizeof(DWORD);
01071                 RegSetValueExW(hSubKey, L"MaxCapacity", 0, REG_DWORD, (LPBYTE)&pItem->dwMaxCapacity, dwSize);
01072                 RegCloseKey(hSubKey);
01073             }
01074         }
01075     }
01076     RegCloseKey(hKey);
01077     return TRUE;
01078 
01079 }
01080 
01081 static VOID FreeDriveItemContext(HWND hwndDlg)
01082 {
01083     int iCount, iIndex;
01084     HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000);
01085     LVITEMW li;
01086 
01087     iCount = ListView_GetItemCount(hDlgCtrl);
01088 
01089     ZeroMemory(&li, sizeof(li));
01090     li.mask = LVIF_PARAM;
01091 
01092     for(iIndex = 0; iIndex < iCount; iIndex++)
01093     {
01094         li.iItem = iIndex;
01095         if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&li))
01096         {
01097             HeapFree(GetProcessHeap(), 0, (LPVOID)li.lParam);
01098         }
01099     }
01100 }
01101 
01102 static INT
01103 GetDefaultItem(HWND hwndDlg, LVITEMW * li)
01104 {
01105     HWND hDlgCtrl;
01106     UINT iItemCount, iIndex;
01107 
01108     hDlgCtrl = GetDlgItem(hwndDlg, 14000);
01109     if (!hDlgCtrl)
01110         return -1;
01111 
01112     iItemCount = ListView_GetItemCount(hDlgCtrl);
01113     if (!iItemCount)
01114         return -1;
01115 
01116     ZeroMemory(li, sizeof(LVITEMW));
01117     li->mask = LVIF_PARAM | LVIF_STATE;
01118     li->stateMask = (UINT) - 1;
01119     for (iIndex = 0; iIndex < iItemCount; iIndex++)
01120     {
01121         li->iItem = iIndex;
01122         if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)li))
01123         {
01124             if (li->state & LVIS_SELECTED)
01125                 return iIndex;
01126         }
01127     }
01128     return -1;
01129 
01130 }
01131 
01132 static INT_PTR CALLBACK
01133 RecycleBinDlg(
01134     HWND hwndDlg,
01135     UINT uMsg,
01136     WPARAM wParam,
01137     LPARAM lParam
01138 )
01139 {
01140     LPPSHNOTIFY lppsn;
01141     LPNMLISTVIEW lppl;
01142     LVITEMW li;
01143     PDRIVE_ITEM_CONTEXT pItem;
01144     BOOL bSuccess;
01145     UINT uResult;
01146     PROPSHEETPAGE * page;
01147     DWORD dwStyle;
01148 
01149     switch(uMsg)
01150     {
01151         case WM_INITDIALOG:
01152             page = (PROPSHEETPAGE*)lParam;
01153             InitializeRecycleBinDlg(hwndDlg, (WCHAR)page->lParam);
01154             dwStyle = (DWORD) SendDlgItemMessage(hwndDlg, 14000, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
01155             dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
01156             SendDlgItemMessage(hwndDlg, 14000, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
01157             if (GetDlgCtrlID((HWND)wParam) != 14000)
01158             {
01159                 SetFocus(GetDlgItem(hwndDlg, 14000));
01160                 return FALSE;
01161             }
01162             return TRUE;
01163         case WM_COMMAND:
01164             switch(LOWORD(wParam))
01165             {
01166                 case 14001:
01167                     toggleNukeOnDeleteOption(hwndDlg, FALSE);
01168                     PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
01169                     break;
01170                 case 14003:
01171                     toggleNukeOnDeleteOption(hwndDlg, TRUE);
01172                     PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
01173                     break;
01174                 case 14004:
01175                     PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
01176                     break;
01177             }
01178             break;
01179         case WM_NOTIFY:
01180             lppsn = (LPPSHNOTIFY) lParam;
01181             lppl = (LPNMLISTVIEW) lParam;
01182             if (lppsn->hdr.code == PSN_APPLY)
01183             {
01184                 if (GetDefaultItem(hwndDlg, &li) > -1)
01185                 {
01186                     pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
01187                     if (pItem)
01188                     {
01189                         uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE);
01190                         if (bSuccess)
01191                             pItem->dwMaxCapacity = uResult;
01192                         if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED)
01193                             pItem->dwNukeOnDelete = TRUE;
01194                         else
01195                             pItem->dwNukeOnDelete = FALSE;
01196                     }
01197                 }
01198                 if (StoreDriveSettings(hwndDlg))
01199                 {
01200                     SetWindowLongPtr( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR );
01201                     return TRUE;
01202                 }
01203             }
01204             else if (lppl->hdr.code == LVN_ITEMCHANGING)
01205             {
01206                 ZeroMemory(&li, sizeof(li));
01207                 li.mask = LVIF_PARAM;
01208                 li.iItem = lppl->iItem;
01209                 if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&li))
01210                     return TRUE;
01211 
01212                 pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
01213                 if (!pItem)
01214                     return TRUE;
01215 
01216                 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
01217                 {
01218                     /* new focused item */
01219                     toggleNukeOnDeleteOption(lppl->hdr.hwndFrom, pItem->dwNukeOnDelete);
01220                     SetDlgItemInt(hwndDlg, 14002, pItem->dwMaxCapacity, FALSE);
01221                 }
01222                 else if ((lppl->uOldState & LVIS_FOCUSED) && !(lppl->uNewState & LVIS_FOCUSED))
01223                 {
01224                     /* kill focus */
01225                     uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE);
01226                     if (bSuccess)
01227                         pItem->dwMaxCapacity = uResult;
01228                     if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED)
01229                         pItem->dwNukeOnDelete = TRUE;
01230                     else
01231                         pItem->dwNukeOnDelete = FALSE;
01232                 }
01233                 return TRUE;
01234 
01235             }
01236             break;
01237         case WM_DESTROY:
01238             FreeDriveItemContext(hwndDlg);
01239             break;
01240     }
01241     return FALSE;
01242 }
01243 
01244 BOOL SH_ShowRecycleBinProperties(WCHAR sDrive)
01245 {
01246     HPROPSHEETPAGE hpsp[1];
01247     PROPSHEETHEADERW psh;
01248     HPROPSHEETPAGE hprop;
01249 
01250     BOOL ret;
01251 
01252 
01253     ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
01254     psh.dwSize = sizeof(PROPSHEETHEADERW);
01255     psh.dwFlags = PSP_DEFAULT | PSH_PROPTITLE;
01256     psh.pszCaption = MAKEINTRESOURCEW(IDS_RECYCLEBIN_FOLDER_NAME);
01257     psh.hwndParent = NULL;
01258     psh.phpage = hpsp;
01259     psh.hInstance = shell32_hInstance;
01260 
01261     hprop = SH_CreatePropertySheetPage(IDD_RECYCLE_BIN_PROPERTIES, RecycleBinDlg, (LPARAM)sDrive, NULL);
01262     if (!hprop)
01263     {
01264         ERR("Failed to create property sheet\n");
01265         return FALSE;
01266     }
01267     hpsp[psh.nPages] = hprop;
01268     psh.nPages++;
01269 
01270 
01271     ret = PropertySheetW(&psh);
01272     if (ret < 0)
01273         return FALSE;
01274     else
01275         return TRUE;
01276 }
01277 
01278 BOOL
01279 TRASH_CanTrashFile(LPCWSTR wszPath)
01280 {
01281     LONG ret;
01282     DWORD dwNukeOnDelete, dwType, VolSerialNumber, MaxComponentLength;
01283     DWORD FileSystemFlags, dwSize, dwDisposition;
01284     HKEY hKey;
01285     WCHAR szBuffer[10];
01286     WCHAR szKey[150] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\";
01287 
01288     if (wszPath[1] != L':')
01289     {
01290         /* path is UNC */
01291         return FALSE;
01292     }
01293 
01294     if (GetDriveTypeW(wszPath) != DRIVE_FIXED)
01295     {
01296         /* no bitbucket on removable media */
01297         return FALSE;
01298     }
01299 
01300     if (!GetVolumeInformationW(wszPath, NULL, 0, &VolSerialNumber, &MaxComponentLength, &FileSystemFlags, NULL, 0))
01301     {
01302         ERR("GetVolumeInformationW failed with %u\n", GetLastError());
01303         return FALSE;
01304     }
01305 
01306     swprintf(szBuffer, L"%04X-%04X", LOWORD(VolSerialNumber), HIWORD(VolSerialNumber));
01307     wcscat(szKey, szBuffer);
01308 
01309     if (RegCreateKeyExW(HKEY_CURRENT_USER, szKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS)
01310     {
01311         ERR("RegCreateKeyExW failed\n");
01312         return FALSE;
01313     }
01314 
01315     if (dwDisposition  & REG_CREATED_NEW_KEY)
01316     {
01317         /* per default move to bitbucket */
01318         dwNukeOnDelete = 0;
01319         RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD));
01320         /* per default unlimited size */
01321         dwSize = -1;
01322         RegSetValueExW(hKey, L"MaxCapacity", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD));
01323         RegCloseKey(hKey);
01324         return TRUE;
01325     }
01326     else
01327     {
01328         dwSize = sizeof(dwNukeOnDelete);
01329         ret = RegQueryValueExW(hKey, L"NukeOnDelete", NULL, &dwType, (LPBYTE)&dwNukeOnDelete, &dwSize);
01330         if (ret != ERROR_SUCCESS)
01331         {
01332             if (ret ==  ERROR_FILE_NOT_FOUND)
01333             {
01334                 /* restore key and enable bitbucket */
01335                 dwNukeOnDelete = 0;
01336                 RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD));
01337             }
01338             RegCloseKey(hKey);
01339             return TRUE;
01340         }
01341         else if (dwNukeOnDelete)
01342         {
01343             /* do not delete to bitbucket */
01344             RegCloseKey(hKey);
01345             return FALSE;
01346         }
01347         /* FIXME
01348          * check if bitbucket is full
01349          */
01350         RegCloseKey(hKey);
01351         return TRUE;
01352     }
01353 }
01354 
01355 BOOL
01356 TRASH_TrashFile(LPCWSTR wszPath)
01357 {
01358     TRACE("(%s)\n", debugstr_w(wszPath));
01359     return DeleteFileToRecycleBin(wszPath);
01360 }
01361 
01362 /*************************************************************************
01363  * SHUpdateCRecycleBinIcon                                [SHELL32.@]
01364  *
01365  * Undocumented
01366  */
01367 EXTERN_C HRESULT WINAPI SHUpdateRecycleBinIcon(void)
01368 {
01369     FIXME("stub\n");
01370 
01371 
01372 
01373     return S_OK;
01374 }

Generated on Mon May 28 2012 04:26:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.