- implement drive extra dialog
[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 YDEBUG
24 #define LARGEINT_PROTOS
25 #define LargeIntegerDivide RtlLargeIntegerDivide
26 #define ExtendedIntegerMultiply RtlExtendedIntegerMultiply
27 #define ConvertUlongToLargeInteger RtlConvertUlongToLargeInteger
28 #define LargeIntegerSubtract RtlLargeIntegerSubtract
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
120 hBlueBrush = CreateSolidBrush(RGB(0, 0, 255));
121 hMagBrush = CreateSolidBrush(RGB(255, 0, 255));
122
123 Result.QuadPart = GetWindowLongPtr(hwndDlg, DWLP_USER);
124
125 CopyRect(&rect, &drawItem->rcItem);
126 horzsize = rect.right - rect.left;
127 Result.QuadPart = (Result.QuadPart * horzsize) / 100;
128
129 rect.right = rect.left + Result.QuadPart;
130 FillRect(drawItem->hDC, &rect, hMagBrush);
131 rect.left = rect.right;
132 rect.right = drawItem->rcItem.right;
133 FillRect(drawItem->hDC, &rect, hBlueBrush);
134 DeleteObject(hBlueBrush);
135 DeleteObject(hMagBrush);
136 }
137 }
138
139 static
140 void
141 InitializeGeneralDriveDialog(HWND hwndDlg, WCHAR * szDrive)
142 {
143 WCHAR szVolumeName[MAX_PATH+1] = {0};
144 DWORD MaxComponentLength = 0;
145 DWORD FileSystemFlags = 0;
146 WCHAR FileSystemName[MAX_PATH+1] = {0};
147 WCHAR szFormat[50];
148 WCHAR szBuffer[128];
149 BOOL ret;
150 UINT DriveType;
151 ULARGE_INTEGER FreeBytesAvailable;
152 LARGE_INTEGER TotalNumberOfFreeBytes;
153 LARGE_INTEGER TotalNumberOfBytes;
154
155 ret = GetVolumeInformationW(szDrive, szVolumeName, MAX_PATH+1, NULL, &MaxComponentLength, &FileSystemFlags, FileSystemName, MAX_PATH+1);
156 if (ret)
157 {
158 /* set volume label */
159 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szVolumeName);
160
161 /* set filesystem type */
162 SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, (WPARAM)NULL, (LPARAM)FileSystemName);
163
164 }
165
166 DriveType = GetDriveTypeW(szDrive);
167 if (DriveType == DRIVE_FIXED)
168 {
169
170 if(GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable, (PULARGE_INTEGER)&TotalNumberOfBytes, (PULARGE_INTEGER)&TotalNumberOfFreeBytes))
171 {
172 WCHAR szResult[128];
173 LARGE_INTEGER Result;
174 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
175 HANDLE hVolume;
176 DWORD BytesReturned = 0;
177
178 sprintfW(szResult, L"\\\\.\\%c:", towupper(szDrive[0]));
179 hVolume = CreateFileW(szResult, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
180 if (hVolume != INVALID_HANDLE_VALUE)
181 {
182 ret = DeviceIoControl(hVolume, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, (LPVOID)&TotalNumberOfBytes, sizeof(ULARGE_INTEGER), &BytesReturned, NULL);
183 if (ret && StrFormatByteSizeW(LengthInformation.Length.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
184 SendDlgItemMessageW(hwndDlg, 14008, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
185
186 CloseHandle(hVolume);
187 }
188 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult), hVolume, ret, LengthInformation.Length.QuadPart, BytesReturned);
189 #else
190 if (ret && StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
191 SendDlgItemMessageW(hwndDlg, 14008, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
192 #endif
193
194 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
195 SendDlgItemMessageW(hwndDlg, 14004, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
196
197 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
198 SendDlgItemMessageW(hwndDlg, 14006, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
199
200 Result = GetFreeBytesShare(TotalNumberOfFreeBytes, TotalNumberOfBytes);
201 /* set free bytes percentage */
202 sprintfW(szResult, L"%02d%%", Result.QuadPart);
203 SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, (WPARAM)0, (LPARAM)szResult);
204 /* store free share amount */
205 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)Result.QuadPart);
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
234 WCHAR * lpstr;
235 switch(uMsg)
236 {
237 case WM_INITDIALOG:
238 ppsp = (LPPROPSHEETPAGEW)lParam;
239 if (ppsp == NULL)
240 break;
241 TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %S\n",hwndDlg, lParam, ppsp->lParam);
242
243 lpstr = (WCHAR *)ppsp->lParam;
244 InitializeGeneralDriveDialog(hwndDlg, lpstr);
245 return TRUE;
246 case WM_DRAWITEM:
247 drawItem = (LPDRAWITEMSTRUCT)lParam;
248 if (drawItem->CtlID >= 14013 && drawItem->CtlID <= 14015)
249 {
250 PaintStaticControls(hwndDlg, drawItem);
251 return TRUE;
252 }
253
254 }
255
256
257 return FALSE;
258 }
259
260 INT_PTR
261 CALLBACK
262 DriveExtraDlg(
263 HWND hwndDlg,
264 UINT uMsg,
265 WPARAM wParam,
266 LPARAM lParam
267 )
268 {
269 STARTUPINFOW si;
270 PROCESS_INFORMATION pi;
271 WCHAR szPath[MAX_PATH];
272 WCHAR szArg[MAX_PATH];
273 WCHAR * szDrive;
274 UINT length;
275 LPPROPSHEETPAGEW ppsp;
276
277 switch (uMsg)
278 {
279 case WM_INITDIALOG:
280 ppsp = (LPPROPSHEETPAGEW)lParam;
281 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam);
282 return TRUE;
283 case WM_COMMAND:
284 ZeroMemory( &si, sizeof(si) );
285 si.cb = sizeof(si);
286 ZeroMemory( &pi, sizeof(pi) );
287 if (!GetSystemDirectoryW(szPath, MAX_PATH))
288 break;
289 szDrive = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
290 switch(LOWORD(wParam))
291 {
292 case 14000:
293 ///
294 /// FIXME
295 /// show checkdsk dialog
296 ///
297 break;
298 case 14001:
299 szArg[0] = L'"';
300 wcscpy(&szArg[1], szPath);
301 wcscat(szPath, L"\\mmc.exe");
302 wcscat(szArg, L"\\dfrg.msc\" ");
303 length = wcslen(szArg);
304 szArg[length] = szDrive[0];
305 szArg[length+1] = L':';
306 szArg[length+2] = L'\0';
307 if (CreateProcessW(szPath, szArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
308 {
309 CloseHandle(pi.hProcess);
310 CloseHandle(pi.hThread);
311 }
312 break;
313 case 14002:
314 wcscat(szPath, L"\\ntbackup.exe");
315 if (CreateProcessW(szPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
316 {
317 CloseHandle(pi.hProcess);
318 CloseHandle(pi.hThread);
319 }
320 }
321 break;
322 }
323 return FALSE;
324 }
325
326 INT_PTR
327 CALLBACK
328 DriveHardwareDlg(
329 HWND hwndDlg,
330 UINT uMsg,
331 WPARAM wParam,
332 LPARAM lParam
333 )
334 {
335 GUID Guids[1];
336 Guids[0] = GUID_DEVCLASS_DISKDRIVE;
337
338 UNREFERENCED_PARAMETER(lParam);
339 UNREFERENCED_PARAMETER(wParam);
340
341 switch(uMsg)
342 {
343 case WM_INITDIALOG:
344 /* create the hardware page */
345 DeviceCreateHardwarePageEx(hwndDlg,
346 Guids,
347 sizeof(Guids) / sizeof(Guids[0]),
348 0);
349 break;
350 }
351
352 return FALSE;
353 }
354
355 static
356 const
357 struct
358 {
359 LPSTR resname;
360 DLGPROC dlgproc;
361 } PropPages[] =
362 {
363 { "DRIVE_GENERAL_DLG", DriveGeneralDlg },
364 { "DRIVE_EXTRA_DLG", DriveExtraDlg },
365 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg },
366 };
367
368 BOOL
369 CALLBACK
370 AddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam)
371 {
372 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
373 if (ppsh != NULL && ppsh->nPages < MAX_PROPERTY_SHEET_PAGE)
374 {
375 ppsh->phpage[ppsh->nPages++] = hpage;
376 return TRUE;
377 }
378 return FALSE;
379 }
380
381 BOOL
382 SH_ShowDriveProperties(WCHAR * drive)
383 {
384 HPSXA hpsx;
385 HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
386 PROPSHEETHEADERW psh;
387 BOOL ret;
388 UINT i;
389
390 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
391 psh.dwSize = sizeof(PROPSHEETHEADER);
392 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
393 psh.hwndParent = NULL;
394 psh.nStartPage = 0;
395 psh.phpage = hpsp;
396
397 for (i = 0; i < DRIVE_PROPERTY_PAGES; i++)
398 {
399 HPROPSHEETPAGE hprop = SH_CreatePropertySheetPage(PropPages[i].resname, PropPages[i].dlgproc, (LPARAM)drive);
400 if (hprop)
401 {
402 hpsp[psh.nPages] = hprop;
403 psh.nPages++;
404 }
405 }
406
407 hpsx = SHCreatePropSheetExtArray(HKEY_CLASSES_ROOT,
408 L"Drive",
409 MAX_PROPERTY_SHEET_PAGE-DRIVE_PROPERTY_PAGES);
410
411 SHAddFromPropSheetExtArray(hpsx,
412 (LPFNADDPROPSHEETPAGE)AddPropSheetPageProc,
413 (LPARAM)&psh);
414
415 ret = PropertySheetW(&psh);
416 if (ret < 0)
417 return FALSE;
418 else
419 return TRUE;
420 }