diff --git a/reactos/dll/win32/shell32/recyclebin.c b/reactos/dll/win32/shell32/recyclebin.c index 8e1d4c4c6cc..6e5d7e6adff 100644 --- a/reactos/dll/win32/shell32/recyclebin.c +++ b/reactos/dll/win32/shell32/recyclebin.c @@ -77,26 +77,6 @@ static const columninfo RecycleBinColumns[] = #define COLUMNS_COUNT 6 -static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME * ft) -{ - FILETIME lft; - SYSTEMTIME time; - int ret; - - FileTimeToLocalFileTime(ft, &lft); - FileTimeToSystemTime(&lft, &time); - - ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, buffer, size); - if (ret>0 && retpFileDetails, dwSize); + if (!ret) + { + pContext->hDeletedFile = hDeletedFile; + pContext->bFound = TRUE; + } + else + CloseRecycleBinHandle(hDeletedFile); + + SHFree(pFileDetails); + return ret; +} + + BOOL WINAPI @@ -286,7 +332,6 @@ CBEnumBitBucket(IN PVOID Context, IN HANDLE hDeletedFile) LPITEMIDLIST pidl = NULL; BOOL ret; - TRACE("CBEnumBitBucket entered\n"); if (!GetDeletedFileDetailsW(hDeletedFile, 0, NULL, @@ -563,6 +608,26 @@ static HRESULT WINAPI RecycleBin_GetDetailsEx(IShellFolder2 *iface, LPCITEMIDLIS return E_NOTIMPL; } +static HRESULT FormatDateTime(LPWSTR buffer, int size, FILETIME * ft) +{ + FILETIME lft; + SYSTEMTIME time; + int ret; + + FileTimeToLocalFileTime(ft, &lft); + FileTimeToSystemTime(&lft, &time); + + ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, buffer, size); + if (ret>0 && ret(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd); + if (lpcmi->lpVerb == MAKEINTRESOURCE(1) || lpcmi->lpVerb == MAKEINTRESOURCE(5)) + { + Context.pFileDetails = _ILGetRecycleStruct(This->apidl); + Context.bFound = FALSE; + + EnumerateRecycleBinW(szDrive, CBSearchBitBucket, (PVOID)&Context); + if (!Context.bFound) + return E_FAIL; + + if (lpcmi->lpVerb == MAKEINTRESOURCE(1)) + { + /* restore file */ + if (RestoreFile(Context.hDeletedFile)) + return S_OK; + else + return E_FAIL; + } + else + { + FIXME("implement delete\n"); + CloseRecycleBinHandle(Context.hDeletedFile); + return E_NOTIMPL; + } + } + else if (lpcmi->lpVerb == MAKEINTRESOURCE(3)) + { + FIXME("implement cut\n"); + return E_NOTIMPL; + } + else if (lpcmi->lpVerb == MAKEINTRESOURCE(7)) + { + FIXME("implement properties\n"); + return E_NOTIMPL; + } + return S_OK; } @@ -1098,9 +1201,10 @@ InitializeBitBucketDlg(HWND hwndDlg, WCHAR DefaultDrive) WCHAR CurDrive = L'A'; WCHAR szDrive[] = L"A:\\"; DWORD dwDrives; - WCHAR szName[30]; + WCHAR szName[100]; WCHAR szVolume[100]; DWORD MaxComponent, Flags; + DWORD dwSerial; LVCOLUMNW lc; HWND hDlgCtrl; LVITEMW li; @@ -1109,7 +1213,8 @@ InitializeBitBucketDlg(HWND hwndDlg, WCHAR DefaultDrive) RECT rect; int columnSize; int defIndex = 0; - DWORD dwNukeOnDelete, dwSize; + DWORD dwSize; + PDRIVE_ITEM_CONTEXT pItem = NULL, pDefault = NULL, pFirst = NULL; hDlgCtrl = GetDlgItem(hwndDlg, 14000); @@ -1147,23 +1252,45 @@ InitializeBitBucketDlg(HWND hwndDlg, WCHAR DefaultDrive) UINT Type = GetDriveTypeW(szDrive); if (Type == DRIVE_FIXED) //FIXME { - if (!GetVolumeInformationW(szDrive, szName, sizeof(szName) / sizeof(WCHAR), NULL, &MaxComponent, &Flags, NULL, 0)) + if (!GetVolumeInformationW(szDrive, szName, sizeof(szName) / sizeof(WCHAR), &dwSerial, &MaxComponent, &Flags, NULL, 0)) { szName[0] = 0; + dwSerial = -1; } + sprintfW(szVolume, L"%s (%c)", szName, szDrive[0]); memset(&li, 0x0, sizeof(LVITEMW)); li.mask = LVIF_TEXT | LVIF_PARAM; li.iSubItem = 0; li.pszText = szVolume; li.iItem = itemCount; - li.lParam = CurDrive; (void)ListView_InsertItemW(hDlgCtrl, &li); if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable , &TotalNumberOfBytes, &TotalNumberOfFreeBytes)) { if (StrFormatByteSizeW(TotalNumberOfFreeBytes.QuadPart, szVolume, sizeof(szVolume) / sizeof(WCHAR))) { - memset(&li, 0x0, sizeof(LVITEMW)); + + pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DRIVE_ITEM_CONTEXT)); + if (pItem) + { + sprintfW(szName, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\%04X-%04X", LOWORD(dwSerial), HIWORD(dwSerial)); + dwSize = sizeof(DWORD); + RegGetValueW(HKEY_CURRENT_USER, szName, L"MaxCapacity", RRF_RT_DWORD, NULL, &pItem->dwMaxCapacity, &dwSize); + dwSize = sizeof(DWORD); + RegGetValueW(HKEY_CURRENT_USER, szName, L"NukeOnDelete", RRF_RT_DWORD, NULL, &pItem->dwNukeOnDelete, &dwSize); + pItem->dwSerial = dwSerial; + li.mask = LVIF_PARAM; + li.lParam = (LPARAM)pItem; + (void)ListView_SetItemW(hDlgCtrl, &li); + if (CurDrive == DefaultDrive) + { + defIndex = itemCount; + pDefault = pItem; + } + } + if (!pFirst) + pFirst = pItem; + li.mask = LVIF_TEXT; li.iSubItem = 1; li.pszText = szVolume; @@ -1171,12 +1298,6 @@ InitializeBitBucketDlg(HWND hwndDlg, WCHAR DefaultDrive) (void)ListView_SetItemW(hDlgCtrl, &li); } } - - if (CurDrive == DefaultDrive) - { - defIndex = itemCount; - } - itemCount++; } } @@ -1185,27 +1306,114 @@ InitializeBitBucketDlg(HWND hwndDlg, WCHAR DefaultDrive) dwDrives = (dwDrives >> 1); }while(dwDrives); + if (!pDefault) + pDefault = pFirst; + if (pDefault) + { + toggleNukeOnDeleteOption(hwndDlg, pDefault->dwNukeOnDelete); + SetDlgItemInt(hwndDlg, 14002, pDefault->dwMaxCapacity, FALSE); + } + ZeroMemory(&li, sizeof(li)); li.mask = LVIF_STATE; - li.state = LVIS_FOCUSED; + li.stateMask = (UINT)-1; + li.state = LVIS_FOCUSED|LVIS_SELECTED; li.iItem = defIndex; (void)ListView_SetItemW(hDlgCtrl, &li); - wcscpy(szVolume, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\c"); - szVolume[62] = DefaultDrive; +} - dwSize = sizeof(dwNukeOnDelete); - if (RegGetValueW(HKEY_LOCAL_MACHINE, szVolume, L"NukeOnDelete", RRF_RT_REG_DWORD, NULL, &dwNukeOnDelete, &dwSize) == ERROR_SUCCESS) +static BOOL StoreDriveSettings(HWND hwndDlg) +{ + int iCount, iIndex; + HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000); + LVITEMW li; + PDRIVE_ITEM_CONTEXT pItem; + HKEY hKey, hSubKey; + WCHAR szSerial[20]; + DWORD dwSize; + + + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume", 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) + return FALSE; + + iCount = ListView_GetItemCount(hDlgCtrl); + + ZeroMemory(&li, sizeof(li)); + li.mask = LVIF_PARAM; + + for(iIndex = 0; iIndex < iCount; iIndex++) { - toggleNukeOnDeleteOption(hwndDlg, dwNukeOnDelete); + li.iItem = iIndex; + if (ListView_GetItemW(hDlgCtrl, &li)) + { + pItem = (PDRIVE_ITEM_CONTEXT)li.lParam; + sprintfW(szSerial, L"%04X-%04X", LOWORD(pItem->dwSerial), HIWORD(pItem->dwSerial)); + if (RegCreateKeyExW(hKey, szSerial, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS) + { + dwSize = sizeof(DWORD); + RegSetValueExW(hSubKey, L"NukeOnDelete", 0, REG_DWORD, (LPVOID)&pItem->dwNukeOnDelete, dwSize); + dwSize = sizeof(DWORD); + RegSetValueExW(hSubKey, L"MaxCapacity", 0, REG_DWORD, (LPVOID)&pItem->dwMaxCapacity, dwSize); + RegCloseKey(hSubKey); + } + } } - else + RegCloseKey(hKey); + return TRUE; + +} + +static VOID FreeDriveItemContext(HWND hwndDlg) +{ + int iCount, iIndex; + HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000); + LVITEMW li; + + iCount = ListView_GetItemCount(hDlgCtrl); + + ZeroMemory(&li, sizeof(li)); + li.mask = LVIF_PARAM; + + for(iIndex = 0; iIndex < iCount; iIndex++) { - /* default to NukeOnDelete - */ - toggleNukeOnDeleteOption(hwndDlg, TRUE); + li.iItem = iIndex; + if (ListView_GetItemW(hDlgCtrl, &li)) + { + HeapFree(GetProcessHeap(), 0, (LPVOID)li.lParam); + } } } +INT +GetDefaultItem(HWND hwndDlg, LVITEMW * li) +{ + HWND hDlgCtrl; + UINT iItemCount, iIndex; + + hDlgCtrl = GetDlgItem(hwndDlg, 14000); + if (!hDlgCtrl) + return -1; + + iItemCount = ListView_GetItemCount(hDlgCtrl); + if (!iItemCount) + return -1; + + ZeroMemory(li, sizeof(LVITEMW)); + li->mask = LVIF_PARAM | LVIF_STATE; + li->stateMask = (UINT)-1; + for (iIndex = 0; iIndex < iItemCount; iIndex++) + { + li->iItem = iIndex; + if (ListView_GetItemW(hDlgCtrl, li)) + { + if (li->state & LVIS_SELECTED) + return iIndex; + } + } + return -1; + +} + INT_PTR CALLBACK BitBucketDlg( @@ -1215,12 +1423,23 @@ BitBucketDlg( LPARAM lParam ) { + LPPSHNOTIFY lppsn; + LPNMLISTVIEW lppl; + LVITEMW li; + PDRIVE_ITEM_CONTEXT pItem; + BOOL bSuccess; + UINT uResult; + switch(uMsg) { case WM_INITDIALOG: InitializeBitBucketDlg(hwndDlg, (WCHAR)lParam); + if (GetDlgCtrlID((HWND)wParam) != 14000) + { + SetFocus(GetDlgItem(hwndDlg, 14000)); + return FALSE; + } return TRUE; - case WM_COMMAND: switch(LOWORD(wParam)) { @@ -1237,6 +1456,67 @@ BitBucketDlg( break; } break; + case WM_NOTIFY: + lppsn = (LPPSHNOTIFY) lParam; + lppl = (LPNMLISTVIEW) lParam; + if (lppsn->hdr.code == PSN_APPLY) + { + if (GetDefaultItem(hwndDlg, &li) > -1) + { + pItem = (PDRIVE_ITEM_CONTEXT)li.lParam; + if (pItem) + { + uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE); + if (bSuccess) + pItem->dwMaxCapacity = uResult; + if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED) + pItem->dwNukeOnDelete = TRUE; + else + pItem->dwNukeOnDelete = FALSE; + } + } + if (StoreDriveSettings(hwndDlg)) + { + SetWindowLong( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR ); + return TRUE; + } + } + else if (lppl->hdr.code == LVN_ITEMCHANGING) + { + ZeroMemory(&li, sizeof(li)); + li.mask = LVIF_PARAM; + li.iItem = lppl->iItem; + if (!ListView_GetItemW(lppl->hdr.hwndFrom, &li)) + return TRUE; + + pItem = (PDRIVE_ITEM_CONTEXT)li.lParam; + if (!pItem) + return TRUE; + + if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED)) + { + /* new focused item */ + toggleNukeOnDeleteOption(lppl->hdr.hwndFrom, pItem->dwNukeOnDelete); + SetDlgItemInt(hwndDlg, 14002, pItem->dwMaxCapacity, FALSE); + } + else if ((lppl->uOldState & LVIS_FOCUSED) && !(lppl->uNewState & LVIS_FOCUSED)) + { + /* kill focus */ + uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE); + if (bSuccess) + pItem->dwMaxCapacity = uResult; + if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED) + pItem->dwNukeOnDelete = TRUE; + else + pItem->dwNukeOnDelete = FALSE; + } + return TRUE; + + } + break; + case WM_DESTROY: + FreeDriveItemContext(hwndDlg); + break; } return FALSE; } @@ -1306,7 +1586,7 @@ TRASH_CanTrashFile(LPCWSTR wszPath) sprintfW(szBuffer, L"%04X-%04X", LOWORD(VolSerialNumber), HIWORD(VolSerialNumber)); wcscat(szKey, szBuffer); - if (RegCreateKeyExW(HKEY_CURRENT_USER, szBuffer, 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS) + if (RegCreateKeyExW(HKEY_CURRENT_USER, szKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS) { ERR("RegCreateKeyExW failed\n"); return FALSE; @@ -1319,7 +1599,7 @@ TRASH_CanTrashFile(LPCWSTR wszPath) RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD)); /* per default unlimited size */ dwSize = -1; - RegSetValueExW(hKey, L"MaxSize", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD)); + RegSetValueExW(hKey, L"MaxCapacity", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD)); RegCloseKey(hKey); return TRUE; } @@ -1329,25 +1609,25 @@ TRASH_CanTrashFile(LPCWSTR wszPath) ret = RegQueryValueExW(hKey, L"NukeOnDelete", NULL, &dwType, (LPBYTE)&dwNukeOnDelete, &dwSize); if (ret != ERROR_SUCCESS) { - sprintfW(szBuffer, L"ret %u\n", ret); - MessageBoxW(NULL, szBuffer, NULL, MB_OK); - RegCloseKey(hKey); if (ret == ERROR_FILE_NOT_FOUND) { /* restore key and enable bitbucket */ dwNukeOnDelete = 0; RegSetValueExW(hKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&dwNukeOnDelete, sizeof(DWORD)); } + RegCloseKey(hKey); return TRUE; } else if (dwNukeOnDelete) { /* do not delete to bitbucket */ + RegCloseKey(hKey); return FALSE; } /* FIXME * check if bitbucket is full */ + RegCloseKey(hKey); return TRUE; } }