[PSDK][REACTOS] Fix definitions and usage of DWLP_MSGRESULT, DWLP_DLGPROC, and DWLP_USER
[reactos.git] / dll / win32 / shell32 / dialogs / recycler_prop.cpp
1 /*
2 * Trash virtual folder support. The trashing engine is implemented in trash.c
3 *
4 * Copyright (C) 2006 Mikolaj Zalewski
5 * Copyright (C) 2009 Andrew Hill
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <precomp.h>
23
24 WINE_DEFAULT_DEBUG_CHANNEL(CRecycleBin);
25
26 typedef struct
27 {
28 DWORD dwNukeOnDelete;
29 DWORD dwSerial;
30 DWORD dwMaxCapacity;
31 } DRIVE_ITEM_CONTEXT, *PDRIVE_ITEM_CONTEXT;
32
33 static void toggleNukeOnDeleteOption(HWND hwndDlg, BOOL bEnable)
34 {
35 if (bEnable)
36 {
37 SendDlgItemMessage(hwndDlg, 14001, BM_SETCHECK, BST_UNCHECKED, 0);
38 EnableWindow(GetDlgItem(hwndDlg, 14002), FALSE);
39 SendDlgItemMessage(hwndDlg, 14003, BM_SETCHECK, BST_CHECKED, 0);
40 }
41 else
42 {
43 SendDlgItemMessage(hwndDlg, 14001, BM_SETCHECK, BST_CHECKED, 0);
44 EnableWindow(GetDlgItem(hwndDlg, 14002), TRUE);
45 SendDlgItemMessage(hwndDlg, 14003, BM_SETCHECK, BST_UNCHECKED, 0);
46 }
47 }
48
49
50 static VOID
51 InitializeRecycleBinDlg(HWND hwndDlg, WCHAR DefaultDrive)
52 {
53 WCHAR CurDrive = L'A';
54 WCHAR szDrive[] = L"A:\\";
55 DWORD dwDrives;
56 WCHAR szName[100];
57 WCHAR szVolume[100];
58 DWORD MaxComponent, Flags;
59 DWORD dwSerial;
60 LVCOLUMNW lc;
61 HWND hDlgCtrl;
62 LVITEMW li;
63 INT itemCount;
64 ULARGE_INTEGER TotalNumberOfFreeBytes, TotalNumberOfBytes, FreeBytesAvailable;
65 RECT rect;
66 int columnSize;
67 int defIndex = 0;
68 DWORD dwSize;
69 PDRIVE_ITEM_CONTEXT pItem = NULL, pDefault = NULL, pFirst = NULL;
70
71 hDlgCtrl = GetDlgItem(hwndDlg, 14000);
72
73 if (!LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_LOCATION, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
74 szVolume[0] = 0;
75
76 GetClientRect(hDlgCtrl, &rect);
77
78 memset(&lc, 0, sizeof(LV_COLUMN) );
79 lc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
80
81 columnSize = 140; //FIXME
82 lc.iSubItem = 0;
83 lc.fmt = LVCFMT_FIXED_WIDTH;
84 lc.cx = columnSize;
85 lc.cchTextMax = wcslen(szVolume);
86 lc.pszText = szVolume;
87 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&lc);
88
89 if (!LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_DISKSPACE, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
90 szVolume[0] = 0;
91
92 lc.iSubItem = 1;
93 lc.cx = rect.right - rect.left - columnSize;
94 lc.cchTextMax = wcslen(szVolume);
95 lc.pszText = szVolume;
96 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&lc);
97
98 dwDrives = GetLogicalDrives();
99 itemCount = 0;
100 do
101 {
102 if ((dwDrives & 0x1))
103 {
104 UINT Type = GetDriveTypeW(szDrive);
105 if (Type == DRIVE_FIXED) //FIXME
106 {
107 if (!GetVolumeInformationW(szDrive, szName, sizeof(szName) / sizeof(WCHAR), &dwSerial, &MaxComponent, &Flags, NULL, 0))
108 {
109 szName[0] = 0;
110 dwSerial = -1;
111 }
112
113 swprintf(szVolume, L"%s (%c:)", szName, szDrive[0]);
114 memset(&li, 0x0, sizeof(LVITEMW));
115 li.mask = LVIF_TEXT | LVIF_PARAM;
116 li.iSubItem = 0;
117 li.pszText = szVolume;
118 li.iItem = itemCount;
119 SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
120 if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable , &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
121 {
122 if (StrFormatByteSizeW(TotalNumberOfFreeBytes.QuadPart, szVolume, sizeof(szVolume) / sizeof(WCHAR)))
123 {
124
125 pItem = (DRIVE_ITEM_CONTEXT *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DRIVE_ITEM_CONTEXT));
126 if (pItem)
127 {
128 swprintf(szName, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume\\%04X-%04X", LOWORD(dwSerial), HIWORD(dwSerial));
129 dwSize = sizeof(DWORD);
130 RegGetValueW(HKEY_CURRENT_USER, szName, L"MaxCapacity", RRF_RT_DWORD, NULL, &pItem->dwMaxCapacity, &dwSize);
131 dwSize = sizeof(DWORD);
132 RegGetValueW(HKEY_CURRENT_USER, szName, L"NukeOnDelete", RRF_RT_DWORD, NULL, &pItem->dwNukeOnDelete, &dwSize);
133 pItem->dwSerial = dwSerial;
134 li.mask = LVIF_PARAM;
135 li.lParam = (LPARAM)pItem;
136 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
137 if (CurDrive == DefaultDrive)
138 {
139 defIndex = itemCount;
140 pDefault = pItem;
141 }
142 }
143 if (!pFirst)
144 pFirst = pItem;
145
146 li.mask = LVIF_TEXT;
147 li.iSubItem = 1;
148 li.pszText = szVolume;
149 li.iItem = itemCount;
150 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
151 }
152 }
153 itemCount++;
154 }
155 }
156 CurDrive++;
157 szDrive[0] = CurDrive;
158 dwDrives = (dwDrives >> 1);
159 } while(dwDrives);
160
161 if (!pDefault)
162 pDefault = pFirst;
163 if (pDefault)
164 {
165 toggleNukeOnDeleteOption(hwndDlg, pDefault->dwNukeOnDelete);
166 SetDlgItemInt(hwndDlg, 14002, pDefault->dwMaxCapacity, FALSE);
167 }
168 ZeroMemory(&li, sizeof(li));
169 li.mask = LVIF_STATE;
170 li.stateMask = (UINT) - 1;
171 li.state = LVIS_FOCUSED | LVIS_SELECTED;
172 li.iItem = defIndex;
173 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
174
175 }
176
177 static BOOL StoreDriveSettings(HWND hwndDlg)
178 {
179 int iCount, iIndex;
180 HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000);
181 LVITEMW li;
182 PDRIVE_ITEM_CONTEXT pItem;
183 HKEY hKey, hSubKey;
184 WCHAR szSerial[20];
185 DWORD dwSize;
186
187
188 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Bitbucket\\Volume", 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
189 return FALSE;
190
191 iCount = ListView_GetItemCount(hDlgCtrl);
192
193 ZeroMemory(&li, sizeof(li));
194 li.mask = LVIF_PARAM;
195
196 for(iIndex = 0; iIndex < iCount; iIndex++)
197 {
198 li.iItem = iIndex;
199 if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&li))
200 {
201 pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
202 swprintf(szSerial, L"%04X-%04X", LOWORD(pItem->dwSerial), HIWORD(pItem->dwSerial));
203 if (RegCreateKeyExW(hKey, szSerial, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
204 {
205 dwSize = sizeof(DWORD);
206 RegSetValueExW(hSubKey, L"NukeOnDelete", 0, REG_DWORD, (LPBYTE)&pItem->dwNukeOnDelete, dwSize);
207 dwSize = sizeof(DWORD);
208 RegSetValueExW(hSubKey, L"MaxCapacity", 0, REG_DWORD, (LPBYTE)&pItem->dwMaxCapacity, dwSize);
209 RegCloseKey(hSubKey);
210 }
211 }
212 }
213 RegCloseKey(hKey);
214 return TRUE;
215
216 }
217
218 static VOID FreeDriveItemContext(HWND hwndDlg)
219 {
220 int iCount, iIndex;
221 HWND hDlgCtrl = GetDlgItem(hwndDlg, 14000);
222 LVITEMW li;
223
224 iCount = ListView_GetItemCount(hDlgCtrl);
225
226 ZeroMemory(&li, sizeof(li));
227 li.mask = LVIF_PARAM;
228
229 for(iIndex = 0; iIndex < iCount; iIndex++)
230 {
231 li.iItem = iIndex;
232 if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&li))
233 {
234 HeapFree(GetProcessHeap(), 0, (LPVOID)li.lParam);
235 }
236 }
237 }
238
239 static INT
240 GetDefaultItem(HWND hwndDlg, LVITEMW * li)
241 {
242 HWND hDlgCtrl;
243 UINT iItemCount, iIndex;
244
245 hDlgCtrl = GetDlgItem(hwndDlg, 14000);
246 if (!hDlgCtrl)
247 return -1;
248
249 iItemCount = ListView_GetItemCount(hDlgCtrl);
250 if (!iItemCount)
251 return -1;
252
253 ZeroMemory(li, sizeof(LVITEMW));
254 li->mask = LVIF_PARAM | LVIF_STATE;
255 li->stateMask = (UINT) - 1;
256 for (iIndex = 0; iIndex < iItemCount; iIndex++)
257 {
258 li->iItem = iIndex;
259 if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)li))
260 {
261 if (li->state & LVIS_SELECTED)
262 return iIndex;
263 }
264 }
265 return -1;
266
267 }
268
269 static INT_PTR CALLBACK
270 RecycleBinDlg(
271 HWND hwndDlg,
272 UINT uMsg,
273 WPARAM wParam,
274 LPARAM lParam
275 )
276 {
277 LPPSHNOTIFY lppsn;
278 LPNMLISTVIEW lppl;
279 LVITEMW li;
280 PDRIVE_ITEM_CONTEXT pItem;
281 BOOL bSuccess;
282 UINT uResult;
283 PROPSHEETPAGE * page;
284 DWORD dwStyle;
285
286 switch(uMsg)
287 {
288 case WM_INITDIALOG:
289 page = (PROPSHEETPAGE*)lParam;
290 InitializeRecycleBinDlg(hwndDlg, (WCHAR)page->lParam);
291 dwStyle = (DWORD) SendDlgItemMessage(hwndDlg, 14000, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
292 dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
293 SendDlgItemMessage(hwndDlg, 14000, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
294 if (GetDlgCtrlID((HWND)wParam) != 14000)
295 {
296 SetFocus(GetDlgItem(hwndDlg, 14000));
297 return FALSE;
298 }
299 return TRUE;
300 case WM_COMMAND:
301 switch(LOWORD(wParam))
302 {
303 case 14001:
304 toggleNukeOnDeleteOption(hwndDlg, FALSE);
305 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
306 break;
307 case 14003:
308 toggleNukeOnDeleteOption(hwndDlg, TRUE);
309 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
310 break;
311 case 14004:
312 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
313 break;
314 }
315 break;
316 case WM_NOTIFY:
317 lppsn = (LPPSHNOTIFY) lParam;
318 lppl = (LPNMLISTVIEW) lParam;
319 if (lppsn->hdr.code == PSN_APPLY)
320 {
321 if (GetDefaultItem(hwndDlg, &li) > -1)
322 {
323 pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
324 if (pItem)
325 {
326 uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE);
327 if (bSuccess)
328 pItem->dwMaxCapacity = uResult;
329 if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED)
330 pItem->dwNukeOnDelete = TRUE;
331 else
332 pItem->dwNukeOnDelete = FALSE;
333 }
334 }
335 if (StoreDriveSettings(hwndDlg))
336 {
337 SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR );
338 return TRUE;
339 }
340 }
341 else if (lppl->hdr.code == LVN_ITEMCHANGING)
342 {
343 ZeroMemory(&li, sizeof(li));
344 li.mask = LVIF_PARAM;
345 li.iItem = lppl->iItem;
346 if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&li))
347 return TRUE;
348
349 pItem = (PDRIVE_ITEM_CONTEXT)li.lParam;
350 if (!pItem)
351 return TRUE;
352
353 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
354 {
355 /* new focused item */
356 toggleNukeOnDeleteOption(lppl->hdr.hwndFrom, pItem->dwNukeOnDelete);
357 SetDlgItemInt(hwndDlg, 14002, pItem->dwMaxCapacity, FALSE);
358 }
359 else if ((lppl->uOldState & LVIS_FOCUSED) && !(lppl->uNewState & LVIS_FOCUSED))
360 {
361 /* kill focus */
362 uResult = GetDlgItemInt(hwndDlg, 14002, &bSuccess, FALSE);
363 if (bSuccess)
364 pItem->dwMaxCapacity = uResult;
365 if (SendDlgItemMessageW(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED)
366 pItem->dwNukeOnDelete = TRUE;
367 else
368 pItem->dwNukeOnDelete = FALSE;
369 }
370 return TRUE;
371
372 }
373 break;
374 case WM_DESTROY:
375 FreeDriveItemContext(hwndDlg);
376 break;
377 }
378 return FALSE;
379 }
380
381 BOOL SH_ShowRecycleBinProperties(WCHAR sDrive)
382 {
383 HPROPSHEETPAGE hpsp[1];
384 PROPSHEETHEADERW psh;
385 HPROPSHEETPAGE hprop;
386
387 BOOL ret;
388
389
390 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
391 psh.dwSize = sizeof(PROPSHEETHEADERW);
392 psh.dwFlags = PSP_DEFAULT | PSH_PROPTITLE;
393 psh.pszCaption = MAKEINTRESOURCEW(IDS_RECYCLEBIN_FOLDER_NAME);
394 psh.hwndParent = NULL;
395 psh.phpage = hpsp;
396 psh.hInstance = shell32_hInstance;
397
398 hprop = SH_CreatePropertySheetPage(IDD_RECYCLE_BIN_PROPERTIES, RecycleBinDlg, (LPARAM)sDrive, NULL);
399 if (!hprop)
400 {
401 ERR("Failed to create property sheet\n");
402 return FALSE;
403 }
404 hpsp[psh.nPages] = hprop;
405 psh.nPages++;
406
407
408 ret = PropertySheetW(&psh);
409 if (ret < 0)
410 return FALSE;
411 else
412 return TRUE;
413 }