- Merge to trunk r37270.
[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 #define LARGEINT_PROTOS
22 #define LargeIntegerDivide RtlLargeIntegerDivide
23 #define ExtendedIntegerMultiply RtlExtendedIntegerMultiply
24 #define ConvertUlongToLargeInteger RtlConvertUlongToLargeInteger
25 #define LargeIntegerSubtract RtlLargeIntegerSubtract
26 #define MAX_PROPERTY_SHEET_PAGE 32
27
28 #define WIN32_NO_STATUS
29 #define NTOS_MODE_USER
30 #define UNICODE
31 #define _UNICODE
32 #define COBJMACROS
33 #include <windows.h>
34 #include <ndk/ntndk.h>
35 #include <fmifs/fmifs.h>
36 #include <largeint.h>
37
38 #include <precomp.h>
39
40 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41
42 typedef enum
43 {
44 HWPD_STANDARDLIST = 0,
45 HWPD_LARGELIST,
46 HWPD_MAX = HWPD_LARGELIST
47 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
48
49 typedef
50 BOOLEAN
51 (NTAPI *INITIALIZE_FMIFS)(
52 IN PVOID hinstDll,
53 IN DWORD dwReason,
54 IN PVOID reserved
55 );
56 typedef
57 BOOLEAN
58 (NTAPI *QUERY_AVAILABLEFSFORMAT)(
59 IN DWORD Index,
60 IN OUT PWCHAR FileSystem,
61 OUT UCHAR* Major,
62 OUT UCHAR* Minor,
63 OUT BOOLEAN* LastestVersion
64 );
65 typedef
66 BOOLEAN
67 (NTAPI *ENABLEVOLUMECOMPRESSION)(
68 IN PWCHAR DriveRoot,
69 IN USHORT Compression
70 );
71
72 typedef
73 VOID
74 (NTAPI *FORMAT_EX)(
75 IN PWCHAR DriveRoot,
76 IN FMIFS_MEDIA_FLAG MediaFlag,
77 IN PWCHAR Format,
78 IN PWCHAR Label,
79 IN BOOLEAN QuickFormat,
80 IN ULONG ClusterSize,
81 IN PFMIFSCALLBACK Callback
82 );
83
84 typedef
85 VOID
86 (NTAPI *CHKDSK)(
87 IN PWCHAR DriveRoot,
88 IN PWCHAR Format,
89 IN BOOLEAN CorrectErrors,
90 IN BOOLEAN Verbose,
91 IN BOOLEAN CheckOnlyIfDirty,
92 IN BOOLEAN ScanDrive,
93 IN PVOID Unused2,
94 IN PVOID Unused3,
95 IN PFMIFSCALLBACK Callback
96 );
97
98
99 typedef struct
100 {
101 WCHAR Drive;
102 UINT Options;
103 HMODULE hLibrary;
104 QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat;
105 FORMAT_EX FormatEx;
106 ENABLEVOLUMECOMPRESSION EnableVolumeCompression;
107 CHKDSK Chkdsk;
108 UINT Result;
109 }FORMAT_DRIVE_CONTEXT, *PFORMAT_DRIVE_CONTEXT;
110
111 BOOL InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext);
112 BOOL GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes);
113 HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
114 HWND WINAPI
115 DeviceCreateHardwarePageEx(HWND hWndParent,
116 LPGUID lpGuids,
117 UINT uNumberOfGuids,
118 HWPAGE_DISPLAYMODE DisplayMode);
119
120 HPROPSHEETPAGE SH_CreatePropertySheetPage(LPSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle);
121
122 #define DRIVE_PROPERTY_PAGES (3)
123
124 static const GUID GUID_DEVCLASS_DISKDRIVE = {0x4d36e967L, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
125
126
127 VOID
128 GetDriveNameWithLetter(LPWSTR szText, UINT Length, WCHAR Drive)
129 {
130 WCHAR szDrive[] = {'C',':','\\', 0};
131 DWORD dwMaxComp, dwFileSys, TempLength = 0;
132
133 szDrive[0] = Drive;
134 if (GetVolumeInformationW(szDrive, szText, Length, NULL, &dwMaxComp, &dwFileSys, NULL, 0))
135 {
136 szText[Length-1] = L'\0';
137 TempLength = wcslen(szText);
138 if (!TempLength)
139 {
140 /* load default volume label */
141 TempLength = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2);
142 }
143 }
144 if (TempLength + 4 < Length)
145 {
146 szText[TempLength] = L' ';
147 szText[TempLength+1] = L'(';
148 szText[TempLength+2] = szDrive[0];
149 szText[TempLength+3] = L')';
150 TempLength +=4;
151 }
152
153 if (TempLength < Length)
154 szText[TempLength] = L'\0';
155 else
156 szText[Length-1] = L'\0';
157 }
158
159
160 VOID
161 InitializeChkDskDialog(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
162 {
163 WCHAR szText[100];
164 UINT Length;
165 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pContext);
166
167 Length = GetWindowTextW(hwndDlg, szText, sizeof(szText)/sizeof(WCHAR));
168
169 GetDriveNameWithLetter(&szText[Length +1], (sizeof(szText)/sizeof(WCHAR))-Length-1, pContext->Drive);
170 szText[Length] = L' ';
171 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
172 SetWindowText(hwndDlg, szText);
173 }
174
175 HWND ChkdskDrvDialog = NULL;
176 BOOLEAN bChkdskSuccess = FALSE;
177
178 BOOLEAN
179 NTAPI
180 ChkdskCallback(
181 IN CALLBACKCOMMAND Command,
182 IN ULONG SubAction,
183 IN PVOID ActionInfo)
184 {
185 PDWORD Progress;
186 PBOOLEAN pSuccess;
187 switch(Command)
188 {
189 case PROGRESS:
190 Progress = (PDWORD)ActionInfo;
191 SendDlgItemMessageW(ChkdskDrvDialog, 14002, PBM_SETPOS, (WPARAM)*Progress, 0);
192 break;
193 case DONE:
194 pSuccess = (PBOOLEAN)ActionInfo;
195 bChkdskSuccess = (*pSuccess);
196 break;
197
198 case VOLUMEINUSE:
199 case INSUFFICIENTRIGHTS:
200 case FSNOTSUPPORTED:
201 case CLUSTERSIZETOOSMALL:
202 bChkdskSuccess = FALSE;
203 FIXME("\n");
204 break;
205
206 default:
207 break;
208 }
209
210 return TRUE;
211 }
212
213 VOID
214 ChkDskNow(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
215 {
216 DWORD ClusterSize = 0, dwMaxComponentLength, FileSystemFlags;
217 WCHAR szFs[30];
218 WCHAR szDrive[] = {'C',':','\\', 0};
219 WCHAR szVolumeLabel[40];
220 ULARGE_INTEGER TotalNumberOfFreeBytes, FreeBytesAvailableUser;
221 BOOLEAN bCorrectErrors = FALSE, bScanDrive = FALSE;
222
223 szDrive[0] = pContext->Drive;
224 if(!GetVolumeInformationW(szDrive, szVolumeLabel, sizeof(szVolumeLabel)/sizeof(WCHAR), NULL, &dwMaxComponentLength, &FileSystemFlags, szFs, sizeof(szFs)/sizeof(WCHAR)))
225 {
226 FIXME("failed to get drive fs type\n");
227 return;
228 }
229
230 if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfFreeBytes, NULL))
231 {
232 FIXME("failed to get drive space type\n");
233 return;
234 }
235
236 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfFreeBytes))
237 {
238 FIXME("invalid cluster size\n");
239 return;
240 }
241
242 if (SendDlgItemMessageW(hwndDlg, 14000, BM_GETCHECK, 0, 0) == BST_CHECKED)
243 bCorrectErrors = TRUE;
244
245 if (SendDlgItemMessageW(hwndDlg, 14001, BM_GETCHECK, 0, 0) == BST_CHECKED)
246 bScanDrive = TRUE;
247
248 ChkdskDrvDialog = hwndDlg;
249 bChkdskSuccess = FALSE;
250 SendDlgItemMessageW(hwndDlg, 14002, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
251 pContext->Chkdsk(szDrive, szFs, bCorrectErrors, TRUE, FALSE, bScanDrive, NULL, NULL, ChkdskCallback);
252
253 ChkdskDrvDialog = NULL;
254 pContext->Result = bChkdskSuccess;
255 bChkdskSuccess = FALSE;
256
257 }
258
259 INT_PTR
260 CALLBACK
261 ChkDskDlg(
262 HWND hwndDlg,
263 UINT uMsg,
264 WPARAM wParam,
265 LPARAM lParam
266 )
267 {
268 PFORMAT_DRIVE_CONTEXT pContext;
269 switch(uMsg)
270 {
271 case WM_INITDIALOG:
272 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
273 InitializeChkDskDialog(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
274 return TRUE;
275 case WM_COMMAND:
276 switch(LOWORD(wParam))
277 {
278 case IDCANCEL:
279 EndDialog(hwndDlg, 0);
280 break;
281 case IDOK:
282 pContext = (PFORMAT_DRIVE_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);
283 ChkDskNow(hwndDlg, pContext);
284 break;
285 }
286 break;
287 }
288
289 return FALSE;
290 }
291
292
293 static
294 LARGE_INTEGER
295 GetFreeBytesShare(LARGE_INTEGER TotalNumberOfFreeBytes, LARGE_INTEGER TotalNumberOfBytes)
296 {
297 LARGE_INTEGER Temp, Result, Remainder;
298
299 if (TotalNumberOfFreeBytes.QuadPart == 0LL)
300 {
301 return ConvertUlongToLargeInteger(0);
302 }
303
304 Temp = LargeIntegerDivide(TotalNumberOfBytes, ConvertUlongToLargeInteger(100), &Remainder);
305 if (Temp.QuadPart >= TotalNumberOfFreeBytes.QuadPart)
306 {
307 Result = ConvertUlongToLargeInteger(1);
308 }else
309 {
310 Result = LargeIntegerDivide(TotalNumberOfFreeBytes, Temp, &Remainder);
311 }
312
313 return Result;
314 }
315
316 static
317 void
318 PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT drawItem)
319 {
320 HBRUSH hBrush;
321
322 if (drawItem->CtlID == 14013)
323 {
324 hBrush = CreateSolidBrush(RGB(0, 0, 255));
325 if (hBrush)
326 {
327 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
328 DeleteObject((HGDIOBJ)hBrush);
329 }
330 }else if (drawItem->CtlID == 14014)
331 {
332 hBrush = CreateSolidBrush(RGB(255, 0, 255));
333 if (hBrush)
334 {
335 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
336 DeleteObject((HGDIOBJ)hBrush);
337 }
338 }
339 else if (drawItem->CtlID == 14015)
340 {
341 HBRUSH hBlueBrush;
342 HBRUSH hMagBrush;
343 RECT rect;
344 LONG horzsize;
345 LARGE_INTEGER Result;
346 WCHAR szBuffer[20];
347
348 hBlueBrush = CreateSolidBrush(RGB(0, 0, 255));
349 hMagBrush = CreateSolidBrush(RGB(255, 0, 255));
350
351 SendDlgItemMessageW(hwndDlg, 14007, WM_GETTEXT, 20, (LPARAM)szBuffer);
352 Result.QuadPart = _wtoi(szBuffer);
353
354 CopyRect(&rect, &drawItem->rcItem);
355 horzsize = rect.right - rect.left;
356 Result.QuadPart = (Result.QuadPart * horzsize) / 100;
357
358 rect.right = drawItem->rcItem.right - Result.QuadPart;
359 FillRect(drawItem->hDC, &rect, hBlueBrush);
360 rect.left = rect.right;
361 rect.right = drawItem->rcItem.right;
362 FillRect(drawItem->hDC, &rect, hMagBrush);
363 DeleteObject(hBlueBrush);
364 DeleteObject(hMagBrush);
365 }
366 }
367
368 static
369 void
370 InitializeGeneralDriveDialog(HWND hwndDlg, WCHAR * szDrive)
371 {
372 WCHAR szVolumeName[MAX_PATH+1] = {0};
373 DWORD MaxComponentLength = 0;
374 DWORD FileSystemFlags = 0;
375 WCHAR FileSystemName[MAX_PATH+1] = {0};
376 WCHAR szFormat[50];
377 WCHAR szBuffer[128];
378 BOOL ret;
379 UINT DriveType;
380 ULARGE_INTEGER FreeBytesAvailable;
381 LARGE_INTEGER TotalNumberOfFreeBytes;
382 LARGE_INTEGER TotalNumberOfBytes;
383
384 ret = GetVolumeInformationW(szDrive, szVolumeName, MAX_PATH+1, NULL, &MaxComponentLength, &FileSystemFlags, FileSystemName, MAX_PATH+1);
385 if (ret)
386 {
387 /* set volume label */
388 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szVolumeName);
389
390 /* set filesystem type */
391 SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, (WPARAM)NULL, (LPARAM)FileSystemName);
392
393 }
394
395 DriveType = GetDriveTypeW(szDrive);
396 if (DriveType == DRIVE_FIXED || DriveType == DRIVE_CDROM)
397 {
398
399 if(GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable, (PULARGE_INTEGER)&TotalNumberOfBytes, (PULARGE_INTEGER)&TotalNumberOfFreeBytes))
400 {
401 WCHAR szResult[128];
402 LARGE_INTEGER Result;
403 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
404 HANDLE hVolume;
405 DWORD BytesReturned = 0;
406
407 swprintf(szResult, L"\\\\.\\%c:", towupper(szDrive[0]));
408 hVolume = CreateFileW(szResult, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
409 if (hVolume != INVALID_HANDLE_VALUE)
410 {
411 ret = DeviceIoControl(hVolume, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, (LPVOID)&TotalNumberOfBytes, sizeof(ULARGE_INTEGER), &BytesReturned, NULL);
412 if (ret && StrFormatByteSizeW(LengthInformation.Length.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
413 SendDlgItemMessageW(hwndDlg, 14008, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
414
415 CloseHandle(hVolume);
416 }
417 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult), hVolume, ret, LengthInformation.Length.QuadPart, BytesReturned);
418 #else
419 if (ret && StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
420 SendDlgItemMessageW(hwndDlg, 14008, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
421 #endif
422
423 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
424 SendDlgItemMessageW(hwndDlg, 14004, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
425
426 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
427 SendDlgItemMessageW(hwndDlg, 14006, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
428
429 Result = GetFreeBytesShare(TotalNumberOfFreeBytes, TotalNumberOfBytes);
430 /* set free bytes percentage */
431 swprintf(szResult, L"%02d%%", Result.QuadPart);
432 SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, (WPARAM)0, (LPARAM)szResult);
433 /* store used share amount */
434 Result = LargeIntegerSubtract(ConvertUlongToLargeInteger(100), Result);
435 swprintf(szResult, L"%02d%%", Result.QuadPart);
436 SendDlgItemMessageW(hwndDlg, 14005, WM_SETTEXT, (WPARAM)0, (LPARAM)szResult);
437 if (LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
438 SendDlgItemMessageW(hwndDlg, 14002, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer);
439
440 }
441 }
442 /* set drive description */
443 SendDlgItemMessageW(hwndDlg, 14010, WM_GETTEXT, (WPARAM)50, (LPARAM)szFormat);
444 swprintf(szBuffer, szFormat, szDrive);
445 SendDlgItemMessageW(hwndDlg, 14010, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szBuffer);
446 }
447
448
449 INT_PTR
450 CALLBACK
451 DriveGeneralDlg(
452 HWND hwndDlg,
453 UINT uMsg,
454 WPARAM wParam,
455 LPARAM lParam
456 )
457 {
458 LPPROPSHEETPAGEW ppsp;
459 LPDRAWITEMSTRUCT drawItem;
460 STARTUPINFOW si;
461 PROCESS_INFORMATION pi;
462 WCHAR * lpstr;
463 WCHAR szPath[MAX_PATH];
464 UINT length;
465 LPPSHNOTIFY lppsn;
466
467 switch(uMsg)
468 {
469 case WM_INITDIALOG:
470 ppsp = (LPPROPSHEETPAGEW)lParam;
471 if (ppsp == NULL)
472 break;
473 lpstr = (WCHAR *)ppsp->lParam;
474 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lpstr);
475 InitializeGeneralDriveDialog(hwndDlg, lpstr);
476 return TRUE;
477 case WM_DRAWITEM:
478 drawItem = (LPDRAWITEMSTRUCT)lParam;
479 if (drawItem->CtlID >= 14013 && drawItem->CtlID <= 14015)
480 {
481 PaintStaticControls(hwndDlg, drawItem);
482 return TRUE;
483 }
484 break;
485 case WM_COMMAND:
486 if (LOWORD(wParam) == 14011)
487 {
488 lpstr = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
489 ZeroMemory( &si, sizeof(si) );
490 si.cb = sizeof(si);
491 ZeroMemory( &pi, sizeof(pi) );
492 if (!GetSystemDirectoryW(szPath, MAX_PATH))
493 break;
494 wcscat(szPath, L"\\cleanmgr.exe /D ");
495 length = wcslen(szPath);
496 szPath[length] = lpstr[0];
497 szPath[length+1] = L'\0';
498 if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
499 {
500 CloseHandle(pi.hProcess);
501 CloseHandle(pi.hThread);
502 }
503 break;
504 }
505 case WM_NOTIFY:
506 lppsn = (LPPSHNOTIFY) lParam;
507 if (LOWORD(wParam) == 14001)
508 {
509 if (HIWORD(wParam) == EN_CHANGE)
510 {
511 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
512 }
513 break;
514 }
515 if (lppsn->hdr.code == PSN_APPLY)
516 {
517 lpstr = (LPWSTR)GetWindowLong(hwndDlg, DWLP_USER);
518 if (lpstr && SendDlgItemMessageW(hwndDlg, 14001, WM_GETTEXT, sizeof(szPath)/sizeof(WCHAR), (LPARAM)szPath))
519 {
520 szPath[(sizeof(szPath)/sizeof(WCHAR))-1] = L'\0';
521 SetVolumeLabelW(lpstr, szPath);
522 }
523 SetWindowLong( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR );
524 return TRUE;
525 }
526 break;
527
528 default:
529 break;
530 }
531
532
533 return FALSE;
534 }
535
536 INT_PTR
537 CALLBACK
538 DriveExtraDlg(
539 HWND hwndDlg,
540 UINT uMsg,
541 WPARAM wParam,
542 LPARAM lParam
543 )
544 {
545 STARTUPINFOW si;
546 PROCESS_INFORMATION pi;
547 WCHAR szPath[MAX_PATH + 10];
548 WCHAR szArg[MAX_PATH];
549 WCHAR * szDrive;
550 LPPROPSHEETPAGEW ppsp;
551 DWORD dwSize;
552 FORMAT_DRIVE_CONTEXT Context;
553
554 switch (uMsg)
555 {
556 case WM_INITDIALOG:
557 ppsp = (LPPROPSHEETPAGEW)lParam;
558 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam);
559 return TRUE;
560 case WM_COMMAND:
561 ZeroMemory( &si, sizeof(si) );
562 si.cb = sizeof(si);
563 ZeroMemory( &pi, sizeof(pi) );
564
565 szDrive = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
566 switch(LOWORD(wParam))
567 {
568 case 14000:
569 if (InitializeFmifsLibrary(&Context))
570 {
571 Context.Drive = szDrive[0];
572 DialogBoxParamW(shell32_hInstance, L"CHKDSK_DLG", hwndDlg, ChkDskDlg, (LPARAM)&Context);
573 FreeLibrary(Context.hLibrary);
574 }
575 break;
576 case 14001:
577 dwSize = sizeof(szPath);
578 if (RegGetValueW(HKEY_LOCAL_MACHINE,
579 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
580 NULL,
581 RRF_RT_REG_EXPAND_SZ,
582 NULL,
583 (PVOID)szPath,
584 &dwSize) == S_OK)
585 {
586 swprintf(szArg, szPath, szDrive[0]);
587 if (!GetSystemDirectoryW(szPath, MAX_PATH))
588 break;
589 szDrive = PathAddBackslashW(szPath);
590 if (!szDrive)
591 break;
592
593 wcscat(szDrive, L"mmc.exe");
594 if (CreateProcessW(szPath, szArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
595 {
596 CloseHandle(pi.hProcess);
597 CloseHandle(pi.hThread);
598 }
599 }
600 break;
601 case 14002:
602 dwSize = sizeof(szPath);
603 if (RegGetValueW(HKEY_LOCAL_MACHINE,
604 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
605 NULL,
606 RRF_RT_REG_EXPAND_SZ,
607 NULL,
608 (PVOID)szPath,
609 &dwSize) == S_OK)
610 {
611 if (CreateProcessW(szPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
612 {
613 CloseHandle(pi.hProcess);
614 CloseHandle(pi.hThread);
615 }
616 }
617 }
618 break;
619 }
620 return FALSE;
621 }
622
623 INT_PTR
624 CALLBACK
625 DriveHardwareDlg(
626 HWND hwndDlg,
627 UINT uMsg,
628 WPARAM wParam,
629 LPARAM lParam
630 )
631 {
632 GUID Guids[1];
633 Guids[0] = GUID_DEVCLASS_DISKDRIVE;
634
635 UNREFERENCED_PARAMETER(lParam);
636 UNREFERENCED_PARAMETER(wParam);
637
638 switch(uMsg)
639 {
640 case WM_INITDIALOG:
641 /* create the hardware page */
642 DeviceCreateHardwarePageEx(hwndDlg,
643 Guids,
644 sizeof(Guids) / sizeof(Guids[0]),
645 0);
646 break;
647 }
648
649 return FALSE;
650 }
651
652 static
653 const
654 struct
655 {
656 LPSTR resname;
657 DLGPROC dlgproc;
658 } PropPages[] =
659 {
660 { "DRIVE_GENERAL_DLG", DriveGeneralDlg },
661 { "DRIVE_EXTRA_DLG", DriveExtraDlg },
662 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg },
663 };
664
665 HRESULT
666 CALLBACK
667 AddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam)
668 {
669 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
670 if (ppsh != NULL && ppsh->nPages < MAX_PROPERTY_SHEET_PAGE)
671 {
672 ppsh->phpage[ppsh->nPages++] = hpage;
673 return TRUE;
674 }
675 return FALSE;
676 }
677
678 BOOL
679 SH_ShowDriveProperties(WCHAR * drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl)
680 {
681 HPSXA hpsx = NULL;
682 HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
683 PROPSHEETHEADERW psh;
684 BOOL ret;
685 UINT i;
686 WCHAR szName[MAX_PATH+6];
687 DWORD dwMaxComponent, dwFileSysFlags;
688 IDataObject * pDataObj = NULL;
689
690 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
691 psh.dwSize = sizeof(PROPSHEETHEADERW);
692 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
693 psh.hwndParent = NULL;
694 psh.nStartPage = 0;
695 psh.phpage = hpsp;
696
697
698 if (GetVolumeInformationW(drive, szName, sizeof(szName)/sizeof(WCHAR), NULL, &dwMaxComponent,
699 &dwFileSysFlags, NULL, 0))
700 {
701 psh.pszCaption = szName;
702 psh.dwFlags |= PSH_PROPTITLE;
703 if (!wcslen(szName))
704 {
705 /* FIXME
706 * check if disk is a really a local hdd
707 */
708 i = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szName, sizeof(szName)/sizeof(WCHAR)-6);
709 if (i > 0 && i < (sizeof(szName)/sizeof(WCHAR)) - 6)
710 {
711 szName[i] = L' ';
712 szName[i+1] = L'(';
713 wcscpy(&szName[i+2], drive);
714 szName[i+4] = L')';
715 szName[i+5] = L'\0';
716 }
717 }
718 }
719
720 for (i = 0; i < DRIVE_PROPERTY_PAGES; i++)
721 {
722 HPROPSHEETPAGE hprop = SH_CreatePropertySheetPage(PropPages[i].resname, PropPages[i].dlgproc, (LPARAM)drive, NULL);
723 if (hprop)
724 {
725 hpsp[psh.nPages] = hprop;
726 psh.nPages++;
727 }
728 }
729 if (SHCreateDataObject(pidlFolder, 1, apidl, NULL, &IID_IDataObject, (void**)&pDataObj) == S_OK)
730 {
731 hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", MAX_PROPERTY_SHEET_PAGE-DRIVE_PROPERTY_PAGES, pDataObj);
732 if (hpsx)
733 {
734 SHAddFromPropSheetExtArray(hpsx, (LPFNADDPROPSHEETPAGE)AddPropSheetPageProc, (LPARAM)&psh);
735 }
736 }
737
738 ret = PropertySheetW(&psh);
739 if (pDataObj)
740 IDataObject_Release(pDataObj);
741
742 if (hpsx)
743 SHDestroyPropSheetExtArray(hpsx);
744
745 if (ret < 0)
746 return FALSE;
747 else
748 return TRUE;
749 }
750
751 BOOL
752 GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes)
753 {
754 DWORD ClusterSize;
755
756 if (!wcsicmp(szFs, L"FAT16") ||
757 !wcsicmp(szFs, L"FAT")) //REACTOS HACK
758 {
759 if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
760 ClusterSize = 2048;
761 else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
762 ClusterSize = 512;
763 else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
764 ClusterSize = 1024;
765 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
766 ClusterSize = 2048;
767 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
768 ClusterSize = 4096;
769 else if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
770 ClusterSize = 8192;
771 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
772 ClusterSize = 16384;
773 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
774 ClusterSize = 32768;
775 else if (TotalNumberOfBytes->QuadPart <= (4096LL * 1024LL * 1024LL))
776 ClusterSize = 8192;
777 else
778 return FALSE;
779 }
780 else if (!wcsicmp(szFs, L"FAT32"))
781 {
782 if (TotalNumberOfBytes->QuadPart <=(64 * 1024 * 1024))
783 ClusterSize = 512;
784 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
785 ClusterSize = 1024;
786 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
787 ClusterSize = 2048;
788 else if (TotalNumberOfBytes->QuadPart <= (8192LL * 1024LL * 1024LL))
789 ClusterSize = 2048;
790 else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
791 ClusterSize = 8192;
792 else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
793 ClusterSize = 16384;
794 else
795 return FALSE;
796 }
797 else if (!wcsicmp(szFs, L"NTFS"))
798 {
799 if (TotalNumberOfBytes->QuadPart <=(512 * 1024 * 1024))
800 ClusterSize = 512;
801 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
802 ClusterSize = 1024;
803 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
804 ClusterSize = 2048;
805 else
806 ClusterSize = 2048;
807 }
808 else
809 return FALSE;
810
811 *pClusterSize = ClusterSize;
812 return TRUE;
813 }
814
815
816 VOID
817 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
818 {
819 WCHAR szFs[100] = {0};
820 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
821 INT iSelIndex;
822 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
823 DWORD ClusterSize;
824 LRESULT lIndex;
825 HWND hDlgCtrl;
826
827 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
828 iSelIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
829 if (iSelIndex == CB_ERR)
830 return;
831
832 if (SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFs) == CB_ERR)
833 return;
834
835 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
836 szDrive[0] = pContext->Drive + 'A';
837
838 if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
839 return;
840
841 if (!wcsicmp(szFs, L"FAT16") ||
842 !wcsicmp(szFs, L"FAT")) //REACTOS HACK
843 {
844 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
845 {
846 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes.QuadPart);
847 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
848 return;
849 }
850
851 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
852 {
853 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
854 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
855 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
856 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
857 if (lIndex != CB_ERR)
858 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
859 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
860 }
861 }
862 else if (!wcsicmp(szFs, L"FAT32"))
863 {
864 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
865 {
866 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes.QuadPart);
867 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
868 return;
869 }
870
871 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
872 {
873 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
874 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
875 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
876 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
877 if (lIndex != CB_ERR)
878 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
879 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
880 }
881 }
882 else if (!wcsicmp(szFs, L"NTFS"))
883 {
884 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
885 {
886 TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes.QuadPart);
887 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
888 return;
889 }
890
891 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
892 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
893 {
894 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
895 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
896 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
897 if (lIndex != CB_ERR)
898 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
899 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
900 }
901 ClusterSize = 512;
902 for (lIndex = 0; lIndex < 4; lIndex++)
903 {
904 TotalNumberOfBytes.QuadPart = ClusterSize;
905 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szFs, sizeof(szFs)/sizeof(WCHAR)))
906 {
907 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
908 if (lIndex != CB_ERR)
909 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
910 }
911 ClusterSize *= 2;
912 }
913 }
914 else
915 {
916 FIXME("unknown fs\n");
917 SendDlgItemMessageW(hwndDlg, 28680, CB_RESETCONTENT, iSelIndex, 0);
918 return;
919 }
920 }
921
922 VOID
923 InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
924 {
925 WCHAR szText[120];
926 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
927 WCHAR szFs[30] = {0};
928 INT Length, TempLength;
929 DWORD dwSerial, dwMaxComp, dwFileSys;
930 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
931 DWORD dwIndex, dwDefault;
932 UCHAR uMinor, uMajor;
933 BOOLEAN Latest;
934 HWND hDlgCtrl;
935
936 Length = GetWindowTextW(hwndDlg, szText, sizeof(szText)/sizeof(WCHAR));
937 if (Length < 0)
938 Length = 0;
939 szDrive[0] = pContext->Drive + L'A';
940 if (GetVolumeInformationW(szDrive, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2, &dwSerial, &dwMaxComp, &dwFileSys, szFs, sizeof(szFs)/sizeof(WCHAR)))
941 {
942 szText[Length] = L' ';
943 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
944 TempLength = wcslen(&szText[Length+1]);
945 if (!TempLength)
946 {
947 /* load default volume label */
948 TempLength = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2);
949 }
950 else
951 {
952 /* set volume label */
953 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
954 SendDlgItemMessageW(hwndDlg, 28679, WM_SETTEXT, 0, (LPARAM)&szText[Length+1]);
955 }
956 Length += TempLength + 1;
957 }
958
959 if (Length + 4 < (sizeof(szText)/sizeof(WCHAR)))
960 {
961 szText[Length] = L' ';
962 szText[Length+1] = L'(';
963 szText[Length+2] = szDrive[0];
964 szText[Length+3] = L')';
965 Length +=4;
966 }
967
968 if (Length < (sizeof(szText)/sizeof(WCHAR)))
969 szText[Length] = L'\0';
970 else
971 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
972
973 /* set window text */
974 SetWindowTextW(hwndDlg, szText);
975
976 if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
977 {
978 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szText, sizeof(szText)/sizeof(WCHAR)))
979 {
980 /* add drive capacity */
981 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
982 SendDlgItemMessageW(hwndDlg, 28673, CB_ADDSTRING, 0, (LPARAM)szText);
983 SendDlgItemMessageW(hwndDlg, 28673, CB_SETCURSEL, 0, (LPARAM)0);
984 }
985 }
986
987 if (pContext->Options & SHFMT_OPT_FULL)
988 {
989 /* check quick format button */
990 SendDlgItemMessageW(hwndDlg, 28674, BM_SETCHECK, BST_CHECKED, 0);
991 }
992
993 /* enumerate all available filesystems */
994 dwIndex = 0;
995 dwDefault = 0;
996 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
997
998 while(pContext->QueryAvailableFileSystemFormat(dwIndex, szText, &uMajor, &uMinor, &Latest))
999 {
1000 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
1001 if (!wcsicmp(szText, szFs))
1002 dwDefault = dwIndex;
1003
1004 SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szText);
1005 dwIndex++;
1006 }
1007
1008 if (!dwIndex)
1009 {
1010 ERR("no filesystem providers\n");
1011 return;
1012 }
1013
1014 /* select default filesys */
1015 SendMessageW(hDlgCtrl, CB_SETCURSEL, dwDefault, 0);
1016 /* setup cluster combo */
1017 InsertDefaultClusterSizeForFs(hwndDlg, pContext);
1018 /* hide progress control */
1019 ShowWindow(GetDlgItem(hwndDlg, 28678), SW_HIDE);
1020 }
1021
1022 HWND FormatDrvDialog = NULL;
1023 BOOLEAN bSuccess = FALSE;
1024
1025
1026 BOOLEAN
1027 NTAPI
1028 FormatExCB(
1029 IN CALLBACKCOMMAND Command,
1030 IN ULONG SubAction,
1031 IN PVOID ActionInfo)
1032 {
1033 PDWORD Progress;
1034 PBOOLEAN pSuccess;
1035 switch(Command)
1036 {
1037 case PROGRESS:
1038 Progress = (PDWORD)ActionInfo;
1039 SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, (WPARAM)*Progress, 0);
1040 break;
1041 case DONE:
1042 pSuccess = (PBOOLEAN)ActionInfo;
1043 bSuccess = (*pSuccess);
1044 break;
1045
1046 case VOLUMEINUSE:
1047 case INSUFFICIENTRIGHTS:
1048 case FSNOTSUPPORTED:
1049 case CLUSTERSIZETOOSMALL:
1050 bSuccess = FALSE;
1051 FIXME("\n");
1052 break;
1053
1054 default:
1055 break;
1056 }
1057
1058 return TRUE;
1059 }
1060
1061
1062
1063
1064
1065 VOID
1066 FormatDrive(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
1067 {
1068 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
1069 WCHAR szFileSys[40] = {0};
1070 WCHAR szLabel[40] = {0};
1071 INT iSelIndex;
1072 UINT Length;
1073 HWND hDlgCtrl;
1074 BOOL QuickFormat;
1075 DWORD ClusterSize;
1076
1077 /* set volume path */
1078 szDrive[0] = pContext->Drive;
1079
1080 /* get filesystem */
1081 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
1082 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
1083 if (iSelIndex == CB_ERR)
1084 {
1085 FIXME("\n");
1086 return;
1087 }
1088 Length = SendMessageW(hDlgCtrl, CB_GETLBTEXTLEN, iSelIndex, 0);
1089 if (Length == CB_ERR || Length + 1> sizeof(szFileSys)/sizeof(WCHAR))
1090 {
1091 FIXME("\n");
1092 return;
1093 }
1094
1095 /* retrieve the file system */
1096 SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFileSys);
1097 szFileSys[(sizeof(szFileSys)/sizeof(WCHAR))-1] = L'\0';
1098
1099 /* retrieve the volume label */
1100 hDlgCtrl = GetWindow(hwndDlg, 28679);
1101 Length = SendMessageW(hDlgCtrl, WM_GETTEXTLENGTH, 0, 0);
1102 if (Length + 1 > sizeof(szLabel)/sizeof(WCHAR))
1103 {
1104 FIXME("\n");
1105 return;
1106 }
1107 SendMessageW(hDlgCtrl, WM_GETTEXT, sizeof(szLabel)/sizeof(WCHAR), (LPARAM)szLabel);
1108 szLabel[(sizeof(szLabel)/sizeof(WCHAR))-1] = L'\0';
1109
1110 /* check for quickformat */
1111 if (SendDlgItemMessageW(hwndDlg, 28674, BM_GETCHECK, 0, 0) == BST_CHECKED)
1112 QuickFormat = TRUE;
1113 else
1114 QuickFormat = FALSE;
1115
1116 /* get the cluster size */
1117 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
1118 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
1119 if (iSelIndex == CB_ERR)
1120 {
1121 FIXME("\n");
1122 return;
1123 }
1124 ClusterSize = SendMessageW(hDlgCtrl, CB_GETITEMDATA, iSelIndex, 0);
1125 if (ClusterSize == CB_ERR)
1126 {
1127 FIXME("\n");
1128 return;
1129 }
1130
1131 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
1132 ShowWindow(hDlgCtrl, SW_SHOW);
1133 SendMessageW(hDlgCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
1134 bSuccess = FALSE;
1135
1136 /* FIXME
1137 * will cause display problems
1138 * when performing more than one format
1139 */
1140 FormatDrvDialog = hwndDlg;
1141
1142 pContext->FormatEx(szDrive,
1143 FMIFS_HARDDISK, /* FIXME */
1144 szFileSys,
1145 szLabel,
1146 QuickFormat,
1147 ClusterSize,
1148 FormatExCB);
1149
1150 ShowWindow(hDlgCtrl, SW_HIDE);
1151 FormatDrvDialog = NULL;
1152 if (!bSuccess)
1153 {
1154 pContext->Result = SHFMT_ERROR;
1155 }
1156 else if (QuickFormat)
1157 {
1158 pContext->Result = SHFMT_OPT_FULL;
1159 }
1160 else
1161 {
1162 pContext->Result = FALSE;
1163 }
1164 }
1165
1166
1167 BOOL
1168 CALLBACK
1169 FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1170 {
1171 PFORMAT_DRIVE_CONTEXT pContext;
1172
1173 switch(uMsg)
1174 {
1175 case WM_INITDIALOG:
1176 InitializeFormatDriveDlg(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
1177 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
1178 return TRUE;
1179 case WM_COMMAND:
1180 switch(LOWORD(wParam))
1181 {
1182 case IDOK:
1183 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1184 FormatDrive(hwndDlg, pContext);
1185 break;
1186 case IDCANCEL:
1187 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1188 EndDialog(hwndDlg, pContext->Result);
1189 break;
1190 case 28677: // filesystem combo
1191 if (HIWORD(wParam) == CBN_SELENDOK)
1192 {
1193 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1194 InsertDefaultClusterSizeForFs(hwndDlg, pContext);
1195 }
1196 break;
1197 }
1198 }
1199 return FALSE;
1200 }
1201
1202
1203 BOOL
1204 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext)
1205 {
1206 INITIALIZE_FMIFS InitFmifs;
1207 BOOLEAN ret;
1208 HMODULE hLibrary;
1209
1210 hLibrary = pContext->hLibrary = LoadLibraryW(L"fmifs.dll");
1211 if(!hLibrary)
1212 {
1213 ERR("failed to load fmifs.dll\n");
1214 return FALSE;
1215 }
1216
1217 InitFmifs = (INITIALIZE_FMIFS)GetProcAddress(hLibrary, "InitializeFmIfs");
1218 if (!InitFmifs)
1219 {
1220 ERR("InitializeFmIfs export is missing\n");
1221 FreeLibrary(hLibrary);
1222 return FALSE;
1223 }
1224
1225 ret = (*InitFmifs)(NULL, DLL_PROCESS_ATTACH, NULL);
1226 if (!ret)
1227 {
1228 ERR("fmifs failed to initialize\n");
1229 FreeLibrary(hLibrary);
1230 return FALSE;
1231 }
1232
1233 pContext->QueryAvailableFileSystemFormat = (QUERY_AVAILABLEFSFORMAT)GetProcAddress(hLibrary, "QueryAvailableFileSystemFormat");
1234 if (!pContext->QueryAvailableFileSystemFormat)
1235 {
1236 ERR("QueryAvailableFileSystemFormat export is missing\n");
1237 FreeLibrary(hLibrary);
1238 return FALSE;
1239 }
1240
1241 pContext->FormatEx = (FORMAT_EX) GetProcAddress(hLibrary, "FormatEx");
1242 if (!pContext->FormatEx)
1243 {
1244 ERR("FormatEx export is missing\n");
1245 FreeLibrary(hLibrary);
1246 return FALSE;
1247 }
1248
1249 pContext->EnableVolumeCompression = (ENABLEVOLUMECOMPRESSION) GetProcAddress(hLibrary, "EnableVolumeCompression");
1250 if (!pContext->FormatEx)
1251 {
1252 ERR("EnableVolumeCompression export is missing\n");
1253 FreeLibrary(hLibrary);
1254 return FALSE;
1255 }
1256
1257 pContext->Chkdsk = (CHKDSK) GetProcAddress(hLibrary, "Chkdsk");
1258 if (!pContext->Chkdsk)
1259 {
1260 ERR("Chkdsk export is missing\n");
1261 FreeLibrary(hLibrary);
1262 return FALSE;
1263 }
1264
1265 return TRUE;
1266 }
1267
1268 /*************************************************************************
1269 * SHFormatDrive (SHELL32.@)
1270 */
1271
1272 DWORD
1273 WINAPI
1274 SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options)
1275 {
1276 FORMAT_DRIVE_CONTEXT Context;
1277 int result;
1278
1279 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd, drive, fmtID, options);
1280
1281 if (!InitializeFmifsLibrary(&Context))
1282 {
1283 ERR("failed to initialize fmifs\n");
1284 return SHFMT_NOFORMAT;
1285 }
1286
1287 Context.Drive = drive;
1288 Context.Options = options;
1289
1290 result = DialogBoxParamW(shell32_hInstance, L"FORMAT_DLG", hwnd, FormatDriveDlg, (LPARAM)&Context);
1291
1292 FreeLibrary(Context.hLibrary);
1293 return result;
1294 }
1295
1296