Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrecyclebin.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
1.7.6.1
|