2 * Shell Library Functions
4 * Copyright 2005 Johannes Anderwald
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.
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.
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
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
30 #define WIN32_NO_STATUS
31 #define NTOS_MODE_USER
35 #include <ndk/ntndk.h>
40 #include "wine/debug.h"
49 #include <fmifs/fmifs.h>
51 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
55 HWPD_STANDARDLIST
= 0,
57 HWPD_MAX
= HWPD_LARGELIST
58 } HWPAGE_DISPLAYMODE
, *PHWPAGE_DISPLAYMODE
;
62 (NTAPI
*INITIALIZE_FMIFS
)(
69 (NTAPI
*QUERY_AVAILABLEFSFORMAT
)(
71 IN OUT PWCHAR FileSystem
,
74 OUT BOOLEAN
* LastestVersion
78 (NTAPI
*ENABLEVOLUMECOMPRESSION
)(
87 IN FMIFS_MEDIA_FLAG MediaFlag
,
90 IN BOOLEAN QuickFormat
,
92 IN PFMIFSCALLBACK Callback
100 IN BOOLEAN CorrectErrors
,
102 IN BOOLEAN CheckOnlyIfDirty
,
103 IN BOOLEAN ScanDrive
,
106 IN PFMIFSCALLBACK Callback
115 QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat
;
117 ENABLEVOLUMECOMPRESSION EnableVolumeCompression
;
120 }FORMAT_DRIVE_CONTEXT
, *PFORMAT_DRIVE_CONTEXT
;
122 BOOL
InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
);
123 BOOL
GetDefaultClusterSize(LPWSTR szFs
, PDWORD pClusterSize
, PULARGE_INTEGER TotalNumberOfBytes
);
126 DeviceCreateHardwarePageEx(HWND hWndParent
,
129 HWPAGE_DISPLAYMODE DisplayMode
);
131 HPROPSHEETPAGE
SH_CreatePropertySheetPage(LPSTR resname
, DLGPROC dlgproc
, LPARAM lParam
, LPWSTR szTitle
);
133 #define DRIVE_PROPERTY_PAGES (3)
135 extern HINSTANCE shell32_hInstance
;
138 GetDriveNameWithLetter(LPWSTR szText
, UINT Length
, WCHAR Drive
)
140 WCHAR szDrive
[] = {'C',':','\\', 0};
141 DWORD dwMaxComp
, dwFileSys
, TempLength
= 0;
144 if (GetVolumeInformationW(szDrive
, szText
, Length
, NULL
, &dwMaxComp
, &dwFileSys
, NULL
, 0))
146 szText
[Length
-1] = L
'\0';
147 TempLength
= wcslen(szText
);
150 /* load default volume label */
151 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
154 if (TempLength
+ 4 < Length
)
156 szText
[TempLength
] = L
' ';
157 szText
[TempLength
+1] = L
'(';
158 szText
[TempLength
+2] = szDrive
[0];
159 szText
[TempLength
+3] = L
')';
163 if (TempLength
< Length
)
164 szText
[TempLength
] = L
'\0';
166 szText
[Length
-1] = L
'\0';
171 InitializeChkDskDialog(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
175 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (INT_PTR
)pContext
);
177 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
179 GetDriveNameWithLetter(&szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))-Length
-1, pContext
->Drive
);
180 szText
[Length
] = L
' ';
181 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
182 SetWindowText(hwndDlg
, szText
);
185 HWND ChkdskDrvDialog
= NULL
;
186 BOOLEAN bChkdskSuccess
= FALSE
;
191 IN CALLBACKCOMMAND Command
,
200 Progress
= (PDWORD
)ActionInfo
;
201 SendDlgItemMessageW(ChkdskDrvDialog
, 14002, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
204 pSuccess
= (PBOOLEAN
)ActionInfo
;
205 bChkdskSuccess
= (*pSuccess
);
209 case INSUFFICIENTRIGHTS
:
211 case CLUSTERSIZETOOSMALL
:
212 bChkdskSuccess
= FALSE
;
224 ChkDskNow(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
226 DWORD ClusterSize
= 0, dwMaxComponentLength
, FileSystemFlags
;
228 WCHAR szDrive
[] = {'C',':','\\', 0};
229 WCHAR szVolumeLabel
[40];
230 ULARGE_INTEGER TotalNumberOfFreeBytes
, FreeBytesAvailableUser
;
231 BOOLEAN bCorrectErrors
= FALSE
, bScanDrive
= FALSE
;
233 szDrive
[0] = pContext
->Drive
;
234 if(!GetVolumeInformationW(szDrive
, szVolumeLabel
, sizeof(szVolumeLabel
)/sizeof(WCHAR
), NULL
, &dwMaxComponentLength
, &FileSystemFlags
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
236 FIXME("failed to get drive fs type\n");
240 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfFreeBytes
, NULL
))
242 FIXME("failed to get drive space type\n");
246 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfFreeBytes
))
248 FIXME("invalid cluster size\n");
252 if (SendDlgItemMessageW(hwndDlg
, 14000, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
253 bCorrectErrors
= TRUE
;
255 if (SendDlgItemMessageW(hwndDlg
, 14001, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
258 ChkdskDrvDialog
= hwndDlg
;
259 bChkdskSuccess
= FALSE
;
260 SendDlgItemMessageW(hwndDlg
, 14002, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
261 pContext
->Chkdsk(szDrive
, szFs
, bCorrectErrors
, TRUE
, FALSE
, bScanDrive
, NULL
, NULL
, ChkdskCallback
);
263 ChkdskDrvDialog
= NULL
;
264 pContext
->Result
= bChkdskSuccess
;
265 bChkdskSuccess
= FALSE
;
278 PFORMAT_DRIVE_CONTEXT pContext
;
282 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
283 InitializeChkDskDialog(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
286 switch(LOWORD(wParam
))
289 EndDialog(hwndDlg
, 0);
292 pContext
= (PFORMAT_DRIVE_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
293 ChkDskNow(hwndDlg
, pContext
);
305 GetFreeBytesShare(LARGE_INTEGER TotalNumberOfFreeBytes
, LARGE_INTEGER TotalNumberOfBytes
)
307 LARGE_INTEGER Temp
, Result
, Remainder
;
309 Temp
= LargeIntegerDivide(TotalNumberOfBytes
, ConvertUlongToLargeInteger(100), &Remainder
);
310 if (Temp
.QuadPart
>= TotalNumberOfFreeBytes
.QuadPart
)
312 Result
= ConvertUlongToLargeInteger(1);
315 Result
= LargeIntegerDivide(TotalNumberOfFreeBytes
, Temp
, &Remainder
);
323 PaintStaticControls(HWND hwndDlg
, LPDRAWITEMSTRUCT drawItem
)
327 if (drawItem
->CtlID
== 14013)
329 hBrush
= CreateSolidBrush(RGB(0, 0, 255));
332 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
333 DeleteObject((HGDIOBJ
)hBrush
);
335 }else if (drawItem
->CtlID
== 14014)
337 hBrush
= CreateSolidBrush(RGB(255, 0, 255));
340 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
341 DeleteObject((HGDIOBJ
)hBrush
);
344 else if (drawItem
->CtlID
== 14015)
350 LARGE_INTEGER Result
;
353 hBlueBrush
= CreateSolidBrush(RGB(0, 0, 255));
354 hMagBrush
= CreateSolidBrush(RGB(255, 0, 255));
356 SendDlgItemMessageW(hwndDlg
, 14007, WM_GETTEXT
, 20, (LPARAM
)szBuffer
);
357 Result
.QuadPart
= _wtoi(szBuffer
);
359 CopyRect(&rect
, &drawItem
->rcItem
);
360 horzsize
= rect
.right
- rect
.left
;
361 Result
.QuadPart
= (Result
.QuadPart
* horzsize
) / 100;
363 rect
.right
= rect
.left
+ Result
.QuadPart
;
364 FillRect(drawItem
->hDC
, &rect
, hMagBrush
);
365 rect
.left
= rect
.right
;
366 rect
.right
= drawItem
->rcItem
.right
;
367 FillRect(drawItem
->hDC
, &rect
, hBlueBrush
);
368 DeleteObject(hBlueBrush
);
369 DeleteObject(hMagBrush
);
375 InitializeGeneralDriveDialog(HWND hwndDlg
, WCHAR
* szDrive
)
377 WCHAR szVolumeName
[MAX_PATH
+1] = {0};
378 DWORD MaxComponentLength
= 0;
379 DWORD FileSystemFlags
= 0;
380 WCHAR FileSystemName
[MAX_PATH
+1] = {0};
385 ULARGE_INTEGER FreeBytesAvailable
;
386 LARGE_INTEGER TotalNumberOfFreeBytes
;
387 LARGE_INTEGER TotalNumberOfBytes
;
389 ret
= GetVolumeInformationW(szDrive
, szVolumeName
, MAX_PATH
+1, NULL
, &MaxComponentLength
, &FileSystemFlags
, FileSystemName
, MAX_PATH
+1);
392 /* set volume label */
393 SendDlgItemMessageW(hwndDlg
, 14001, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szVolumeName
);
395 /* set filesystem type */
396 SendDlgItemMessageW(hwndDlg
, 14003, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)FileSystemName
);
400 DriveType
= GetDriveTypeW(szDrive
);
401 if (DriveType
== DRIVE_FIXED
)
404 if(GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailable
, (PULARGE_INTEGER
)&TotalNumberOfBytes
, (PULARGE_INTEGER
)&TotalNumberOfFreeBytes
))
407 LARGE_INTEGER Result
;
408 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
410 DWORD BytesReturned
= 0;
412 sprintfW(szResult
, L
"\\\\.\\%c:", towupper(szDrive
[0]));
413 hVolume
= CreateFileW(szResult
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
414 if (hVolume
!= INVALID_HANDLE_VALUE
)
416 ret
= DeviceIoControl(hVolume
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, (LPVOID
)&TotalNumberOfBytes
, sizeof(ULARGE_INTEGER
), &BytesReturned
, NULL
);
417 if (ret
&& StrFormatByteSizeW(LengthInformation
.Length
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
418 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
420 CloseHandle(hVolume
);
422 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult
), hVolume
, ret
, LengthInformation
.Length
.QuadPart
, BytesReturned
);
424 if (ret
&& StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
425 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
428 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
- FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
429 SendDlgItemMessageW(hwndDlg
, 14004, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
431 if (StrFormatByteSizeW(FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
432 SendDlgItemMessageW(hwndDlg
, 14006, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
434 Result
= GetFreeBytesShare(TotalNumberOfFreeBytes
, TotalNumberOfBytes
);
435 /* set free bytes percentage */
436 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
437 SendDlgItemMessageW(hwndDlg
, 14007, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
438 /* store used share amount */
439 Result
= LargeIntegerSubtract(ConvertUlongToLargeInteger(100), Result
);
440 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
441 SendDlgItemMessageW(hwndDlg
, 14005, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
442 if (LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
443 SendDlgItemMessageW(hwndDlg
, 14002, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szBuffer
);
447 /* set drive description */
448 SendDlgItemMessageW(hwndDlg
, 14010, WM_GETTEXT
, (WPARAM
)50, (LPARAM
)szFormat
);
449 swprintf(szBuffer
, szFormat
, szDrive
);
450 SendDlgItemMessageW(hwndDlg
, 14010, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szBuffer
);
463 LPPROPSHEETPAGEW ppsp
;
464 LPDRAWITEMSTRUCT drawItem
;
466 PROCESS_INFORMATION pi
;
468 WCHAR szPath
[MAX_PATH
];
475 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
478 lpstr
= (WCHAR
*)ppsp
->lParam
;
479 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lpstr
);
480 InitializeGeneralDriveDialog(hwndDlg
, lpstr
);
483 drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
484 if (drawItem
->CtlID
>= 14013 && drawItem
->CtlID
<= 14015)
486 PaintStaticControls(hwndDlg
, drawItem
);
491 if (LOWORD(wParam
) == 14011)
493 lpstr
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
494 ZeroMemory( &si
, sizeof(si
) );
496 ZeroMemory( &pi
, sizeof(pi
) );
497 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
499 wcscat(szPath
, L
"\\cleanmgr.exe /D ");
500 length
= wcslen(szPath
);
501 szPath
[length
] = lpstr
[0];
502 szPath
[length
+1] = L
'\0';
503 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
505 CloseHandle(pi
.hProcess
);
506 CloseHandle(pi
.hThread
);
511 lppsn
= (LPPSHNOTIFY
) lParam
;
512 if (LOWORD(wParam
) == 14001)
514 if (HIWORD(wParam
) == EN_CHANGE
)
516 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
520 if (lppsn
->hdr
.code
== PSN_APPLY
)
522 lpstr
= (LPWSTR
)GetWindowLong(hwndDlg
, DWLP_USER
);
523 if (lpstr
&& SendDlgItemMessageW(hwndDlg
, 14001, WM_GETTEXT
, sizeof(szPath
)/sizeof(WCHAR
), (LPARAM
)szPath
))
525 szPath
[(sizeof(szPath
)/sizeof(WCHAR
))-1] = L
'\0';
526 SetVolumeLabelW(lpstr
, szPath
);
528 SetWindowLong( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
551 PROCESS_INFORMATION pi
;
552 WCHAR szPath
[MAX_PATH
+ 10];
553 WCHAR szArg
[MAX_PATH
];
555 LPPROPSHEETPAGEW ppsp
;
557 FORMAT_DRIVE_CONTEXT Context
;
562 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
563 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)ppsp
->lParam
);
566 ZeroMemory( &si
, sizeof(si
) );
568 ZeroMemory( &pi
, sizeof(pi
) );
570 szDrive
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
571 switch(LOWORD(wParam
))
574 if (InitializeFmifsLibrary(&Context
))
576 Context
.Drive
= szDrive
[0];
577 DialogBoxParamW(shell32_hInstance
, L
"CHKDSK_DLG", hwndDlg
, ChkDskDlg
, (LPARAM
)&Context
);
578 FreeLibrary(Context
.hLibrary
);
582 dwSize
= sizeof(szPath
);
583 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
584 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
586 RRF_RT_REG_EXPAND_SZ
,
591 swprintf(szArg
, szPath
, szDrive
[0]);
592 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
594 szDrive
= PathAddBackslashW(szPath
);
598 wcscat(szDrive
, L
"mmc.exe");
599 if (CreateProcessW(szPath
, szArg
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
601 CloseHandle(pi
.hProcess
);
602 CloseHandle(pi
.hThread
);
607 dwSize
= sizeof(szPath
);
608 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
609 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
611 RRF_RT_REG_EXPAND_SZ
,
616 if (CreateProcessW(szPath
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
618 CloseHandle(pi
.hProcess
);
619 CloseHandle(pi
.hThread
);
638 Guids
[0] = GUID_DEVCLASS_DISKDRIVE
;
640 UNREFERENCED_PARAMETER(lParam
);
641 UNREFERENCED_PARAMETER(wParam
);
646 /* create the hardware page */
647 DeviceCreateHardwarePageEx(hwndDlg
,
649 sizeof(Guids
) / sizeof(Guids
[0]),
665 { "DRIVE_GENERAL_DLG", DriveGeneralDlg
},
666 { "DRIVE_EXTRA_DLG", DriveExtraDlg
},
667 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg
},
672 AddPropSheetPageProc(HPROPSHEETPAGE hpage
, LPARAM lParam
)
674 PROPSHEETHEADER
*ppsh
= (PROPSHEETHEADER
*)lParam
;
675 if (ppsh
!= NULL
&& ppsh
->nPages
< MAX_PROPERTY_SHEET_PAGE
)
677 ppsh
->phpage
[ppsh
->nPages
++] = hpage
;
684 SH_ShowDriveProperties(WCHAR
* drive
)
687 HPROPSHEETPAGE hpsp
[MAX_PROPERTY_SHEET_PAGE
];
688 PROPSHEETHEADERW psh
;
691 WCHAR szName
[MAX_PATH
];
692 DWORD dwMaxComponent
, dwFileSysFlags
;
694 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
695 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
696 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
697 psh
.hwndParent
= NULL
;
702 if (GetVolumeInformationW(drive
, szName
, sizeof(szName
)/sizeof(WCHAR
), NULL
, &dwMaxComponent
,
703 &dwFileSysFlags
, NULL
, 0))
705 psh
.pszCaption
= szName
;
706 psh
.dwFlags
|= PSH_PROPTITLE
;
710 * check if disk is a really a local hdd
712 i
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szName
, sizeof(szName
)/sizeof(WCHAR
));
713 if (i
> 0 && i
< (sizeof(szName
)/sizeof(WCHAR
)) + 6)
717 wcscpy(&szName
[i
+2], drive
);
725 for (i
= 0; i
< DRIVE_PROPERTY_PAGES
; i
++)
727 HPROPSHEETPAGE hprop
= SH_CreatePropertySheetPage(PropPages
[i
].resname
, PropPages
[i
].dlgproc
, (LPARAM
)drive
, NULL
);
730 hpsp
[psh
.nPages
] = hprop
;
735 hpsx
= SHCreatePropSheetExtArray(HKEY_CLASSES_ROOT
,
737 MAX_PROPERTY_SHEET_PAGE
-DRIVE_PROPERTY_PAGES
);
739 SHAddFromPropSheetExtArray(hpsx
,
740 (LPFNADDPROPSHEETPAGE
)AddPropSheetPageProc
,
743 ret
= PropertySheetW(&psh
);
751 GetDefaultClusterSize(LPWSTR szFs
, PDWORD pClusterSize
, PULARGE_INTEGER TotalNumberOfBytes
)
755 if (!wcsicmp(szFs
, L
"FAT16") ||
756 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
758 if (TotalNumberOfBytes
->QuadPart
<= (16 * 1024 * 1024))
760 else if (TotalNumberOfBytes
->QuadPart
<= (32 * 1024 * 1024))
762 else if (TotalNumberOfBytes
->QuadPart
<= (64 * 1024 * 1024))
764 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
766 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
768 else if (TotalNumberOfBytes
->QuadPart
<= (512 * 1024 * 1024))
770 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
772 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
774 else if (TotalNumberOfBytes
->QuadPart
<= (4096LL * 1024LL * 1024LL))
779 else if (!wcsicmp(szFs
, L
"FAT32"))
781 if (TotalNumberOfBytes
->QuadPart
<=(64 * 1024 * 1024))
783 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
785 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
787 else if (TotalNumberOfBytes
->QuadPart
<= (8192LL * 1024LL * 1024LL))
789 else if (TotalNumberOfBytes
->QuadPart
<= (16384LL * 1024LL * 1024LL))
791 else if (TotalNumberOfBytes
->QuadPart
<= (32768LL * 1024LL * 1024LL))
796 else if (!wcsicmp(szFs
, L
"NTFS"))
798 if (TotalNumberOfBytes
->QuadPart
<=(512 * 1024 * 1024))
800 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
802 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
810 *pClusterSize
= ClusterSize
;
816 InsertDefaultClusterSizeForFs(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
818 WCHAR szFs
[100] = {0};
819 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
821 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
826 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
827 iSelIndex
= SendMessage(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
828 if (iSelIndex
== CB_ERR
)
831 if (SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFs
) == CB_ERR
)
834 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
835 szDrive
[0] = pContext
->Drive
+ 'A';
837 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
840 if (!wcsicmp(szFs
, L
"FAT16") ||
841 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
843 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
845 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes
.QuadPart
);
846 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
850 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
852 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
853 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
854 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
855 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
856 if (lIndex
!= CB_ERR
)
857 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
858 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
861 else if (!wcsicmp(szFs
, L
"FAT32"))
863 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
865 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes
.QuadPart
);
866 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
870 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
872 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
873 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
874 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
875 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
876 if (lIndex
!= CB_ERR
)
877 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
878 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
881 else if (!wcsicmp(szFs
, L
"NTFS"))
883 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
885 TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes
.QuadPart
);
886 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
890 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
891 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
893 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
894 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
895 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
896 if (lIndex
!= CB_ERR
)
897 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
898 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
901 for (lIndex
= 0; lIndex
< 4; lIndex
++)
903 TotalNumberOfBytes
.QuadPart
= ClusterSize
;
904 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
906 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
907 if (lIndex
!= CB_ERR
)
908 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
915 FIXME("unknown fs\n");
916 SendDlgItemMessageW(hwndDlg
, 28680, CB_RESETCONTENT
, iSelIndex
, 0);
922 InitializeFormatDriveDlg(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
925 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
926 WCHAR szFs
[30] = {0};
927 INT Length
, TempLength
;
928 DWORD dwSerial
, dwMaxComp
, dwFileSys
;
929 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
930 DWORD dwIndex
, dwDefault
;
931 UCHAR uMinor
, uMajor
;
935 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
936 szDrive
[0] = pContext
->Drive
+ L
'A';
937 if (GetVolumeInformationW(szDrive
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2, &dwSerial
, &dwMaxComp
, &dwFileSys
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
939 szText
[Length
] = L
' ';
940 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
941 TempLength
= wcslen(&szText
[Length
+1]);
944 /* load default volume label */
945 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
949 /* set volume label */
950 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
951 SendDlgItemMessageW(hwndDlg
, 28679, WM_SETTEXT
, 0, (LPARAM
)&szText
[Length
+1]);
953 Length
+= TempLength
+ 1;
956 if (Length
+ 4 < (sizeof(szText
)/sizeof(WCHAR
)))
958 szText
[Length
] = L
' ';
959 szText
[Length
+1] = L
'(';
960 szText
[Length
+2] = szDrive
[0];
961 szText
[Length
+3] = L
')';
965 if (Length
< (sizeof(szText
)/sizeof(WCHAR
)))
966 szText
[Length
] = L
'\0';
968 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
970 /* set window text */
971 SetWindowTextW(hwndDlg
, szText
);
973 if (GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
975 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szText
, sizeof(szText
)/sizeof(WCHAR
)))
977 /* add drive capacity */
978 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
979 SendDlgItemMessageW(hwndDlg
, 28673, CB_ADDSTRING
, 0, (LPARAM
)szText
);
980 SendDlgItemMessageW(hwndDlg
, 28673, CB_SETCURSEL
, 0, (LPARAM
)0);
984 if (pContext
->Options
& SHFMT_OPT_FULL
)
986 /* check quick format button */
987 SendDlgItemMessageW(hwndDlg
, 28674, BM_SETCHECK
, BST_CHECKED
, 0);
990 /* enumerate all available filesystems */
993 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
995 while(pContext
->QueryAvailableFileSystemFormat(dwIndex
, szText
, &uMajor
, &uMinor
, &Latest
))
997 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
998 if (!wcsicmp(szText
, szFs
))
1001 SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szText
);
1007 ERR("no filesystem providers\n");
1011 /* select default filesys */
1012 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, dwDefault
, 0);
1013 /* setup cluster combo */
1014 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
1015 /* hide progress control */
1016 ShowWindow(GetDlgItem(hwndDlg
, 28678), SW_HIDE
);
1019 HWND FormatDrvDialog
= NULL
;
1020 BOOLEAN bSuccess
= FALSE
;
1026 IN CALLBACKCOMMAND Command
,
1028 IN PVOID ActionInfo
)
1035 Progress
= (PDWORD
)ActionInfo
;
1036 SendDlgItemMessageW(FormatDrvDialog
, 28678, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
1039 pSuccess
= (PBOOLEAN
)ActionInfo
;
1040 bSuccess
= (*pSuccess
);
1044 case INSUFFICIENTRIGHTS
:
1045 case FSNOTSUPPORTED
:
1046 case CLUSTERSIZETOOSMALL
:
1063 FormatDrive(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
1065 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
1066 WCHAR szFileSys
[40] = {0};
1067 WCHAR szLabel
[40] = {0};
1074 /* set volume path */
1075 szDrive
[0] = pContext
->Drive
;
1077 /* get filesystem */
1078 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
1079 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1080 if (iSelIndex
== CB_ERR
)
1085 Length
= SendMessageW(hDlgCtrl
, CB_GETLBTEXTLEN
, iSelIndex
, 0);
1086 if (Length
== CB_ERR
|| Length
+ 1> sizeof(szFileSys
)/sizeof(WCHAR
))
1092 /* retrieve the file system */
1093 SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFileSys
);
1094 szFileSys
[(sizeof(szFileSys
)/sizeof(WCHAR
))-1] = L
'\0';
1096 /* retrieve the volume label */
1097 hDlgCtrl
= GetWindow(hwndDlg
, 28679);
1098 Length
= SendMessageW(hDlgCtrl
, WM_GETTEXTLENGTH
, 0, 0);
1099 if (Length
+ 1 > sizeof(szLabel
)/sizeof(WCHAR
))
1104 SendMessageW(hDlgCtrl
, WM_GETTEXT
, sizeof(szLabel
)/sizeof(WCHAR
), (LPARAM
)szLabel
);
1105 szLabel
[(sizeof(szLabel
)/sizeof(WCHAR
))-1] = L
'\0';
1107 /* check for quickformat */
1108 if (SendDlgItemMessageW(hwndDlg
, 28674, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1111 QuickFormat
= FALSE
;
1113 /* get the cluster size */
1114 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1115 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1116 if (iSelIndex
== CB_ERR
)
1121 ClusterSize
= SendMessageW(hDlgCtrl
, CB_GETITEMDATA
, iSelIndex
, 0);
1122 if (ClusterSize
== CB_ERR
)
1128 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1129 ShowWindow(hDlgCtrl
, SW_SHOW
);
1130 SendMessageW(hDlgCtrl
, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
1134 * will cause display problems
1135 * when performing more than one format
1137 FormatDrvDialog
= hwndDlg
;
1139 pContext
->FormatEx(szDrive
,
1140 FMIFS_HARDDISK
, /* FIXME */
1147 ShowWindow(hDlgCtrl
, SW_HIDE
);
1148 FormatDrvDialog
= NULL
;
1151 pContext
->Result
= SHFMT_ERROR
;
1153 else if (QuickFormat
)
1155 pContext
->Result
= SHFMT_OPT_FULL
;
1159 pContext
->Result
= FALSE
;
1166 FormatDriveDlg(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1168 PFORMAT_DRIVE_CONTEXT pContext
;
1173 InitializeFormatDriveDlg(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
1174 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
1177 switch(LOWORD(wParam
))
1180 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1181 FormatDrive(hwndDlg
, pContext
);
1184 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1185 EndDialog(hwndDlg
, pContext
->Result
);
1187 case 28677: // filesystem combo
1188 if (HIWORD(wParam
) == CBN_SELENDOK
)
1190 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1191 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
1201 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
)
1203 INITIALIZE_FMIFS InitFmifs
;
1207 hLibrary
= pContext
->hLibrary
= LoadLibraryW(L
"fmifs.dll");
1210 ERR("failed to load fmifs.dll\n");
1214 InitFmifs
= (INITIALIZE_FMIFS
)GetProcAddress(hLibrary
, "InitializeFmIfs");
1217 ERR("InitializeFmIfs export is missing\n");
1218 FreeLibrary(hLibrary
);
1222 ret
= (*InitFmifs
)(NULL
, DLL_PROCESS_ATTACH
, NULL
);
1225 ERR("fmifs failed to initialize\n");
1226 FreeLibrary(hLibrary
);
1230 pContext
->QueryAvailableFileSystemFormat
= (QUERY_AVAILABLEFSFORMAT
)GetProcAddress(hLibrary
, "QueryAvailableFileSystemFormat");
1231 if (!pContext
->QueryAvailableFileSystemFormat
)
1233 ERR("QueryAvailableFileSystemFormat export is missing\n");
1234 FreeLibrary(hLibrary
);
1238 pContext
->FormatEx
= (FORMAT_EX
) GetProcAddress(hLibrary
, "FormatEx");
1239 if (!pContext
->FormatEx
)
1241 ERR("FormatEx export is missing\n");
1242 FreeLibrary(hLibrary
);
1246 pContext
->EnableVolumeCompression
= (ENABLEVOLUMECOMPRESSION
) GetProcAddress(hLibrary
, "EnableVolumeCompression");
1247 if (!pContext
->FormatEx
)
1249 ERR("EnableVolumeCompression export is missing\n");
1250 FreeLibrary(hLibrary
);
1254 pContext
->Chkdsk
= (CHKDSK
) GetProcAddress(hLibrary
, "Chkdsk");
1255 if (!pContext
->Chkdsk
)
1257 ERR("Chkdsk export is missing\n");
1258 FreeLibrary(hLibrary
);
1265 /*************************************************************************
1266 * SHFormatDrive (SHELL32.@)
1271 SHFormatDrive(HWND hwnd
, UINT drive
, UINT fmtID
, UINT options
)
1273 FORMAT_DRIVE_CONTEXT Context
;
1276 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd
, drive
, fmtID
, options
);
1278 if (!InitializeFmifsLibrary(&Context
))
1280 ERR("failed to initialize fmifs\n");
1281 return SHFMT_NOFORMAT
;
1284 Context
.Drive
= drive
;
1285 Context
.Options
= options
;
1287 result
= DialogBoxParamW(shell32_hInstance
, L
"FORMAT_DLG", hwnd
, FormatDriveDlg
, (LPARAM
)&Context
);
1289 FreeLibrary(Context
.hLibrary
);