- Sync up Mm interface with WinLdr branch (introduce the concept of a memory type...
[reactos.git] / reactos / dll / win32 / shell32 / drive.c
1 /*
2 * Shell Library Functions
3 *
4 * Copyright 2005 Johannes Anderwald
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "config.h"
22 #include "wine/port.h"
23 #define LARGEINT_PROTOS
24 #define LargeIntegerDivide RtlLargeIntegerDivide
25 #define ExtendedIntegerMultiply RtlExtendedIntegerMultiply
26 #define ConvertUlongToLargeInteger RtlConvertUlongToLargeInteger
27 #define LargeIntegerSubtract RtlLargeIntegerSubtract
28 #define MAX_PROPERTY_SHEET_PAGE 32
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include "winerror.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winreg.h"
36 #include "wingdi.h"
37 #include "winuser.h"
38 #include "commdlg.h"
39 #include "wine/debug.h"
40
41 #include "shellapi.h"
42 #include <shlwapi.h>
43 #include "shlobj.h"
44 #include "shell32_main.h"
45 #include "shresdef.h"
46 #include "undocshell.h"
47 #include <prsht.h>
48 #include <initguid.h>
49 #include <devguid.h>
50 #include <winioctl.h>
51 #include <largeint.h>
52
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54
55 typedef enum
56 {
57 HWPD_STANDARDLIST = 0,
58 HWPD_LARGELIST,
59 HWPD_MAX = HWPD_LARGELIST
60 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
61
62 HWND WINAPI
63 DeviceCreateHardwarePageEx(HWND hWndParent,
64 LPGUID lpGuids,
65 UINT uNumberOfGuids,
66 HWPAGE_DISPLAYMODE DisplayMode);
67
68 #define DRIVE_PROPERTY_PAGES (3)
69
70
71 static
72 LARGE_INTEGER
73 GetFreeBytesShare(LARGE_INTEGER TotalNumberOfFreeBytes, LARGE_INTEGER TotalNumberOfBytes)
74 {
75 LARGE_INTEGER Temp, Result, Remainder;
76
77 Temp = LargeIntegerDivide(TotalNumberOfBytes, ConvertUlongToLargeInteger(100), &Remainder);
78 if (Temp.QuadPart >= TotalNumberOfFreeBytes.QuadPart)
79 {
80 Result = ConvertUlongToLargeInteger(1);
81 }else
82 {
83 Result = LargeIntegerDivide(TotalNumberOfFreeBytes, Temp, &Remainder);
84 }
85
86 return Result;
87 }
88
89 static
90 void
91 PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT drawItem)
92 {
93 HBRUSH hBrush;
94
95 if (drawItem->CtlID == 14013)
96 {
97 hBrush = CreateSolidBrush(RGB(0, 0, 255));
98 if (hBrush)
99 {
100 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
101 DeleteObject((HGDIOBJ)hBrush);
102 }
103 }else if (drawItem->CtlID == 14014)
104 {
105 hBrush = CreateSolidBrush(RGB(255, 0, 255));
106 if (hBrush)
107 {
108 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
109 DeleteObject((HGDIOBJ)hBrush);
110 }
111 }
112 else if (drawItem->CtlID == 14015)
113 {
114 HBRUSH hBlueBrush;
115 HBRUSH hMagBrush;
116 RECT rect;
117 LONG horzsize;
118 LARGE_INTEGER Result;
119 WCHAR szBuffer[20];
120
121 hBlueBrush = CreateSolidBrush(RGB(0, 0, 255));
122 hMagBrush = CreateSolidBrush(RGB(255, 0, 255));
123
124 SendDlgItemMessageW(hwndDlg, 14007, WM_GETTEXT, 20, (LPARAM)szBuffer);
125 Result.QuadPart = _wtoi(szBuffer);
126
127 CopyRect(&rect, &drawItem->rcItem);
128 horzsize = rect.right - rect.left;
129 Result.QuadPart = (Result.QuadPart * horzsize) / 100;
130
131 rect.right = rect.left + Result.QuadPart;
132 FillRect(drawItem->hDC, &rect, hMagBrush);
133 rect.left = rect.right;
134 rect.right = drawItem->rcItem.right;
135 FillRect(drawItem->hDC, &rect, hBlueBrush);
136 DeleteObject(hBlueBrush);
137 DeleteObject(hMagBrush);
138 }
139 }
140
141 static
142 void
143 InitializeGeneralDriveDialog(HWND hwndDlg, WCHAR * szDrive)
144 {
145 WCHAR szVolumeName[MAX_PATH+1] = {0};
146 DWORD MaxComponentLength = 0;
147 DWORD FileSystemFlags = 0;
148 WCHAR FileSystemName[MAX_PATH+1] = {0};
149 WCHAR szFormat[50];
150 WCHAR szBuffer[128];
151 BOOL ret;
152 UINT DriveType;
153 ULARGE_INTEGER FreeBytesAvailable;
154 LARGE_INTEGER TotalNumberOfFreeBytes;
155 LARGE_INTEGER TotalNumberOfBytes;
156
157 ret = GetVolumeInformationW(szDrive, szVolumeName, MAX_PATH+1, NULL, &MaxComponentLength, &FileSystemFlags, FileSystemName, MAX_PATH+1);
158 if (ret)
159 {
160 /* set volume label */
161 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szVolumeName);
162
163 /* set filesystem type */
164 SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, (WPARAM)NULL, (LPARAM)FileSystemName);
165
166 }
167
168 DriveType = GetDriveTypeW(szDrive);
169 if (DriveType == DRIVE_FIXED)
170 {
171
172 if(GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable, (PULARGE_INTEGER)&TotalNumberOfBytes, (PULARGE_INTEGER)&TotalNumberOfFreeBytes))
173 {
174 WCHAR szResult[128];
175 LARGE_INTEGER Result;
176 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
177 HANDLE hVolume;
178 DWORD BytesReturned = 0;
179
180 sprintfW(szResult, L"\\\\.\\%c:", towupper(szDrive[0]));
181 hVolume = CreateFileW(szResult, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
182 if (hVolume != INVALID_HANDLE_VALUE)
183 {
184 ret = DeviceIoControl(hVolume, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, (LPVOID)&TotalNumberOfBytes, sizeof(ULARGE_INTEGER), &BytesReturned, NULL);
185 if (ret && StrFormatByteSizeW(LengthInformation.Length.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
186 SendDlgItemMessageW(hwndDlg, 14008, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
187
188 CloseHandle(hVolume);
189 }
190 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult), hVolume, ret, LengthInformation.Length.QuadPart, BytesReturned);
191 #else
192 if (ret && StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
193 SendDlgItemMessageW(hwndDlg, 14008, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
194 #endif
195
196 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
197 SendDlgItemMessageW(hwndDlg, 14004, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
198
199 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
200 SendDlgItemMessageW(hwndDlg, 14006, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
201
202 Result = GetFreeBytesShare(TotalNumberOfFreeBytes, TotalNumberOfBytes);
203 /* set free bytes percentage */
204 sprintfW(szResult, L"%02d%%", Result.QuadPart);
205 SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, (WPARAM)0, (LPARAM)szResult);
206 /* store used share amount */
207 Result = LargeIntegerSubtract(ConvertUlongToLargeInteger(100), Result);
208 sprintfW(szResult, L"%02d%%", Result.QuadPart);
209 SendDlgItemMessageW(hwndDlg, 14005, WM_SETTEXT, (WPARAM)0, (LPARAM)szResult);
210 if (LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
211 SendDlgItemMessageW(hwndDlg, 14002, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer);
212
213 }
214 }
215 /* set drive description */
216 SendDlgItemMessageW(hwndDlg, 14010, WM_GETTEXT, (WPARAM)50, (LPARAM)szFormat);
217 sprintfW(szBuffer, szFormat, szDrive);
218 SendDlgItemMessageW(hwndDlg, 14010, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szBuffer);
219 }
220
221
222 INT_PTR
223 CALLBACK
224 DriveGeneralDlg(
225 HWND hwndDlg,
226 UINT uMsg,
227 WPARAM wParam,
228 LPARAM lParam
229 )
230 {
231 LPPROPSHEETPAGEW ppsp;
232 LPDRAWITEMSTRUCT drawItem;
233 STARTUPINFOW si;
234 PROCESS_INFORMATION pi;
235 WCHAR * lpstr;
236 WCHAR szPath[MAX_PATH];
237 UINT length;
238
239 switch(uMsg)
240 {
241 case WM_INITDIALOG:
242 ppsp = (LPPROPSHEETPAGEW)lParam;
243 if (ppsp == NULL)
244 break;
245 lpstr = (WCHAR *)ppsp->lParam;
246 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lpstr);
247 InitializeGeneralDriveDialog(hwndDlg, lpstr);
248 return TRUE;
249 case WM_DRAWITEM:
250 drawItem = (LPDRAWITEMSTRUCT)lParam;
251 if (drawItem->CtlID >= 14013 && drawItem->CtlID <= 14015)
252 {
253 PaintStaticControls(hwndDlg, drawItem);
254 return TRUE;
255 }
256 break;
257 case WM_COMMAND:
258 if (LOWORD(wParam) == 14011)
259 {
260 lpstr = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
261 ZeroMemory( &si, sizeof(si) );
262 si.cb = sizeof(si);
263 ZeroMemory( &pi, sizeof(pi) );
264 if (!GetSystemDirectoryW(szPath, MAX_PATH))
265 break;
266 wcscat(szPath, L"\\cleanmgr.exe /D ");
267 length = wcslen(szPath);
268 szPath[length] = lpstr[0];
269 szPath[length+1] = L'\0';
270 if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
271 {
272 CloseHandle(pi.hProcess);
273 CloseHandle(pi.hThread);
274 }
275 }
276 break;
277 }
278
279
280 return FALSE;
281 }
282
283 INT_PTR
284 CALLBACK
285 DriveExtraDlg(
286 HWND hwndDlg,
287 UINT uMsg,
288 WPARAM wParam,
289 LPARAM lParam
290 )
291 {
292 STARTUPINFOW si;
293 PROCESS_INFORMATION pi;
294 WCHAR szPath[MAX_PATH];
295 WCHAR szArg[MAX_PATH];
296 WCHAR * szDrive;
297 UINT length;
298 LPPROPSHEETPAGEW ppsp;
299
300 switch (uMsg)
301 {
302 case WM_INITDIALOG:
303 ppsp = (LPPROPSHEETPAGEW)lParam;
304 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam);
305 return TRUE;
306 case WM_COMMAND:
307 ZeroMemory( &si, sizeof(si) );
308 si.cb = sizeof(si);
309 ZeroMemory( &pi, sizeof(pi) );
310 if (!GetSystemDirectoryW(szPath, MAX_PATH))
311 break;
312 szDrive = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
313 switch(LOWORD(wParam))
314 {
315 case 14000:
316 ///
317 /// FIXME
318 /// show checkdsk dialog
319 ///
320 break;
321 case 14001:
322 szArg[0] = L'"';
323 wcscpy(&szArg[1], szPath);
324 wcscat(szPath, L"\\mmc.exe");
325 wcscat(szArg, L"\\dfrg.msc\" ");
326 length = wcslen(szArg);
327 szArg[length] = szDrive[0];
328 szArg[length+1] = L':';
329 szArg[length+2] = L'\0';
330 if (CreateProcessW(szPath, szArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
331 {
332 CloseHandle(pi.hProcess);
333 CloseHandle(pi.hThread);
334 }
335 break;
336 case 14002:
337 wcscat(szPath, L"\\ntbackup.exe");
338 if (CreateProcessW(szPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
339 {
340 CloseHandle(pi.hProcess);
341 CloseHandle(pi.hThread);
342 }
343 }
344 break;
345 }
346 return FALSE;
347 }
348
349 INT_PTR
350 CALLBACK
351 DriveHardwareDlg(
352 HWND hwndDlg,
353 UINT uMsg,
354 WPARAM wParam,
355 LPARAM lParam
356 )
357 {
358 GUID Guids[1];
359 Guids[0] = GUID_DEVCLASS_DISKDRIVE;
360
361 UNREFERENCED_PARAMETER(lParam);
362 UNREFERENCED_PARAMETER(wParam);
363
364 switch(uMsg)
365 {
366 case WM_INITDIALOG:
367 /* create the hardware page */
368 DeviceCreateHardwarePageEx(hwndDlg,
369 Guids,
370 sizeof(Guids) / sizeof(Guids[0]),
371 0);
372 break;
373 }
374
375 return FALSE;
376 }
377
378 static
379 const
380 struct
381 {
382 LPSTR resname;
383 DLGPROC dlgproc;
384 } PropPages[] =
385 {
386 { "DRIVE_GENERAL_DLG", DriveGeneralDlg },
387 { "DRIVE_EXTRA_DLG", DriveExtraDlg },
388 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg },
389 };
390
391 BOOL
392 CALLBACK
393 AddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam)
394 {
395 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
396 if (ppsh != NULL && ppsh->nPages < MAX_PROPERTY_SHEET_PAGE)
397 {
398 ppsh->phpage[ppsh->nPages++] = hpage;
399 return TRUE;
400 }
401 return FALSE;
402 }
403
404 BOOL
405 SH_ShowDriveProperties(WCHAR * drive)
406 {
407 HPSXA hpsx;
408 HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
409 PROPSHEETHEADERW psh;
410 BOOL ret;
411 UINT i;
412
413 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
414 psh.dwSize = sizeof(PROPSHEETHEADERW);
415 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
416 psh.hwndParent = NULL;
417 psh.nStartPage = 0;
418 psh.phpage = hpsp;
419
420 for (i = 0; i < DRIVE_PROPERTY_PAGES; i++)
421 {
422 HPROPSHEETPAGE hprop = SH_CreatePropertySheetPage(PropPages[i].resname, PropPages[i].dlgproc, (LPARAM)drive, NULL);
423 if (hprop)
424 {
425 hpsp[psh.nPages] = hprop;
426 psh.nPages++;
427 }
428 }
429
430 hpsx = SHCreatePropSheetExtArray(HKEY_CLASSES_ROOT,
431 L"Drive",
432 MAX_PROPERTY_SHEET_PAGE-DRIVE_PROPERTY_PAGES);
433
434 SHAddFromPropSheetExtArray(hpsx,
435 (LPFNADDPROPSHEETPAGE)AddPropSheetPageProc,
436 (LPARAM)&psh);
437
438 ret = PropertySheetW(&psh);
439 if (ret < 0)
440 return FALSE;
441 else
442 return TRUE;
443 }