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
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
28 #define WIN32_NO_STATUS
29 #define NTOS_MODE_USER
34 #include <ndk/ntndk.h>
35 #include <fmifs/fmifs.h>
40 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
44 HWPD_STANDARDLIST
= 0,
46 HWPD_MAX
= HWPD_LARGELIST
47 } HWPAGE_DISPLAYMODE
, *PHWPAGE_DISPLAYMODE
;
51 (NTAPI
*INITIALIZE_FMIFS
)(
58 (NTAPI
*QUERY_AVAILABLEFSFORMAT
)(
60 IN OUT PWCHAR FileSystem
,
63 OUT BOOLEAN
* LastestVersion
67 (NTAPI
*ENABLEVOLUMECOMPRESSION
)(
76 IN FMIFS_MEDIA_FLAG MediaFlag
,
79 IN BOOLEAN QuickFormat
,
81 IN PFMIFSCALLBACK Callback
89 IN BOOLEAN CorrectErrors
,
91 IN BOOLEAN CheckOnlyIfDirty
,
95 IN PFMIFSCALLBACK Callback
104 QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat
;
106 ENABLEVOLUMECOMPRESSION EnableVolumeCompression
;
109 }FORMAT_DRIVE_CONTEXT
, *PFORMAT_DRIVE_CONTEXT
;
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
);
115 DeviceCreateHardwarePageEx(HWND hWndParent
,
118 HWPAGE_DISPLAYMODE DisplayMode
);
120 HPROPSHEETPAGE
SH_CreatePropertySheetPage(LPSTR resname
, DLGPROC dlgproc
, LPARAM lParam
, LPWSTR szTitle
);
122 #define DRIVE_PROPERTY_PAGES (3)
124 static const GUID GUID_DEVCLASS_DISKDRIVE
= {0x4d36e967L
, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
128 GetDriveNameWithLetter(LPWSTR szText
, UINT Length
, WCHAR Drive
)
130 WCHAR szDrive
[] = {'C',':','\\', 0};
131 DWORD dwMaxComp
, dwFileSys
, TempLength
= 0;
134 if (GetVolumeInformationW(szDrive
, szText
, Length
, NULL
, &dwMaxComp
, &dwFileSys
, NULL
, 0))
136 szText
[Length
-1] = L
'\0';
137 TempLength
= wcslen(szText
);
140 /* load default volume label */
141 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
144 if (TempLength
+ 4 < Length
)
146 szText
[TempLength
] = L
' ';
147 szText
[TempLength
+1] = L
'(';
148 szText
[TempLength
+2] = szDrive
[0];
149 szText
[TempLength
+3] = L
')';
153 if (TempLength
< Length
)
154 szText
[TempLength
] = L
'\0';
156 szText
[Length
-1] = L
'\0';
161 InitializeChkDskDialog(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
165 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (INT_PTR
)pContext
);
167 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
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
);
175 HWND ChkdskDrvDialog
= NULL
;
176 BOOLEAN bChkdskSuccess
= FALSE
;
181 IN CALLBACKCOMMAND Command
,
190 Progress
= (PDWORD
)ActionInfo
;
191 SendDlgItemMessageW(ChkdskDrvDialog
, 14002, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
194 pSuccess
= (PBOOLEAN
)ActionInfo
;
195 bChkdskSuccess
= (*pSuccess
);
199 case INSUFFICIENTRIGHTS
:
201 case CLUSTERSIZETOOSMALL
:
202 bChkdskSuccess
= FALSE
;
214 ChkDskNow(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
216 DWORD ClusterSize
= 0, dwMaxComponentLength
, FileSystemFlags
;
218 WCHAR szDrive
[] = {'C',':','\\', 0};
219 WCHAR szVolumeLabel
[40];
220 ULARGE_INTEGER TotalNumberOfFreeBytes
, FreeBytesAvailableUser
;
221 BOOLEAN bCorrectErrors
= FALSE
, bScanDrive
= FALSE
;
223 szDrive
[0] = pContext
->Drive
;
224 if(!GetVolumeInformationW(szDrive
, szVolumeLabel
, sizeof(szVolumeLabel
)/sizeof(WCHAR
), NULL
, &dwMaxComponentLength
, &FileSystemFlags
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
226 FIXME("failed to get drive fs type\n");
230 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfFreeBytes
, NULL
))
232 FIXME("failed to get drive space type\n");
236 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfFreeBytes
))
238 FIXME("invalid cluster size\n");
242 if (SendDlgItemMessageW(hwndDlg
, 14000, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
243 bCorrectErrors
= TRUE
;
245 if (SendDlgItemMessageW(hwndDlg
, 14001, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
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
);
253 ChkdskDrvDialog
= NULL
;
254 pContext
->Result
= bChkdskSuccess
;
255 bChkdskSuccess
= FALSE
;
268 PFORMAT_DRIVE_CONTEXT pContext
;
272 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
273 InitializeChkDskDialog(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
276 switch(LOWORD(wParam
))
279 EndDialog(hwndDlg
, 0);
282 pContext
= (PFORMAT_DRIVE_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
283 ChkDskNow(hwndDlg
, pContext
);
295 GetFreeBytesShare(LARGE_INTEGER TotalNumberOfFreeBytes
, LARGE_INTEGER TotalNumberOfBytes
)
297 LARGE_INTEGER Temp
, Result
, Remainder
;
299 Temp
= LargeIntegerDivide(TotalNumberOfBytes
, ConvertUlongToLargeInteger(100), &Remainder
);
300 if (Temp
.QuadPart
>= TotalNumberOfFreeBytes
.QuadPart
)
302 Result
= ConvertUlongToLargeInteger(1);
305 Result
= LargeIntegerDivide(TotalNumberOfFreeBytes
, Temp
, &Remainder
);
313 PaintStaticControls(HWND hwndDlg
, LPDRAWITEMSTRUCT drawItem
)
317 if (drawItem
->CtlID
== 14013)
319 hBrush
= CreateSolidBrush(RGB(0, 0, 255));
322 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
323 DeleteObject((HGDIOBJ
)hBrush
);
325 }else if (drawItem
->CtlID
== 14014)
327 hBrush
= CreateSolidBrush(RGB(255, 0, 255));
330 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
331 DeleteObject((HGDIOBJ
)hBrush
);
334 else if (drawItem
->CtlID
== 14015)
340 LARGE_INTEGER Result
;
343 hBlueBrush
= CreateSolidBrush(RGB(0, 0, 255));
344 hMagBrush
= CreateSolidBrush(RGB(255, 0, 255));
346 SendDlgItemMessageW(hwndDlg
, 14007, WM_GETTEXT
, 20, (LPARAM
)szBuffer
);
347 Result
.QuadPart
= _wtoi(szBuffer
);
349 CopyRect(&rect
, &drawItem
->rcItem
);
350 horzsize
= rect
.right
- rect
.left
;
351 Result
.QuadPart
= (Result
.QuadPart
* horzsize
) / 100;
353 rect
.right
= drawItem
->rcItem
.right
- Result
.QuadPart
;
354 FillRect(drawItem
->hDC
, &rect
, hBlueBrush
);
355 rect
.left
= rect
.right
;
356 rect
.right
= drawItem
->rcItem
.right
;
357 FillRect(drawItem
->hDC
, &rect
, hMagBrush
);
358 DeleteObject(hBlueBrush
);
359 DeleteObject(hMagBrush
);
365 InitializeGeneralDriveDialog(HWND hwndDlg
, WCHAR
* szDrive
)
367 WCHAR szVolumeName
[MAX_PATH
+1] = {0};
368 DWORD MaxComponentLength
= 0;
369 DWORD FileSystemFlags
= 0;
370 WCHAR FileSystemName
[MAX_PATH
+1] = {0};
375 ULARGE_INTEGER FreeBytesAvailable
;
376 LARGE_INTEGER TotalNumberOfFreeBytes
;
377 LARGE_INTEGER TotalNumberOfBytes
;
379 ret
= GetVolumeInformationW(szDrive
, szVolumeName
, MAX_PATH
+1, NULL
, &MaxComponentLength
, &FileSystemFlags
, FileSystemName
, MAX_PATH
+1);
382 /* set volume label */
383 SendDlgItemMessageW(hwndDlg
, 14001, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szVolumeName
);
385 /* set filesystem type */
386 SendDlgItemMessageW(hwndDlg
, 14003, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)FileSystemName
);
390 DriveType
= GetDriveTypeW(szDrive
);
391 if (DriveType
== DRIVE_FIXED
)
394 if(GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailable
, (PULARGE_INTEGER
)&TotalNumberOfBytes
, (PULARGE_INTEGER
)&TotalNumberOfFreeBytes
))
397 LARGE_INTEGER Result
;
398 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
400 DWORD BytesReturned
= 0;
402 swprintf(szResult
, L
"\\\\.\\%c:", towupper(szDrive
[0]));
403 hVolume
= CreateFileW(szResult
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
404 if (hVolume
!= INVALID_HANDLE_VALUE
)
406 ret
= DeviceIoControl(hVolume
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, (LPVOID
)&TotalNumberOfBytes
, sizeof(ULARGE_INTEGER
), &BytesReturned
, NULL
);
407 if (ret
&& StrFormatByteSizeW(LengthInformation
.Length
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
408 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
410 CloseHandle(hVolume
);
412 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult
), hVolume
, ret
, LengthInformation
.Length
.QuadPart
, BytesReturned
);
414 if (ret
&& StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
415 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
418 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
- FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
419 SendDlgItemMessageW(hwndDlg
, 14004, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
421 if (StrFormatByteSizeW(FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
422 SendDlgItemMessageW(hwndDlg
, 14006, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
424 Result
= GetFreeBytesShare(TotalNumberOfFreeBytes
, TotalNumberOfBytes
);
425 /* set free bytes percentage */
426 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
427 SendDlgItemMessageW(hwndDlg
, 14007, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
428 /* store used share amount */
429 Result
= LargeIntegerSubtract(ConvertUlongToLargeInteger(100), Result
);
430 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
431 SendDlgItemMessageW(hwndDlg
, 14005, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
432 if (LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
433 SendDlgItemMessageW(hwndDlg
, 14002, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szBuffer
);
437 /* set drive description */
438 SendDlgItemMessageW(hwndDlg
, 14010, WM_GETTEXT
, (WPARAM
)50, (LPARAM
)szFormat
);
439 swprintf(szBuffer
, szFormat
, szDrive
);
440 SendDlgItemMessageW(hwndDlg
, 14010, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szBuffer
);
453 LPPROPSHEETPAGEW ppsp
;
454 LPDRAWITEMSTRUCT drawItem
;
456 PROCESS_INFORMATION pi
;
458 WCHAR szPath
[MAX_PATH
];
465 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
468 lpstr
= (WCHAR
*)ppsp
->lParam
;
469 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lpstr
);
470 InitializeGeneralDriveDialog(hwndDlg
, lpstr
);
473 drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
474 if (drawItem
->CtlID
>= 14013 && drawItem
->CtlID
<= 14015)
476 PaintStaticControls(hwndDlg
, drawItem
);
481 if (LOWORD(wParam
) == 14011)
483 lpstr
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
484 ZeroMemory( &si
, sizeof(si
) );
486 ZeroMemory( &pi
, sizeof(pi
) );
487 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
489 wcscat(szPath
, L
"\\cleanmgr.exe /D ");
490 length
= wcslen(szPath
);
491 szPath
[length
] = lpstr
[0];
492 szPath
[length
+1] = L
'\0';
493 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
495 CloseHandle(pi
.hProcess
);
496 CloseHandle(pi
.hThread
);
501 lppsn
= (LPPSHNOTIFY
) lParam
;
502 if (LOWORD(wParam
) == 14001)
504 if (HIWORD(wParam
) == EN_CHANGE
)
506 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
510 if (lppsn
->hdr
.code
== PSN_APPLY
)
512 lpstr
= (LPWSTR
)GetWindowLong(hwndDlg
, DWLP_USER
);
513 if (lpstr
&& SendDlgItemMessageW(hwndDlg
, 14001, WM_GETTEXT
, sizeof(szPath
)/sizeof(WCHAR
), (LPARAM
)szPath
))
515 szPath
[(sizeof(szPath
)/sizeof(WCHAR
))-1] = L
'\0';
516 SetVolumeLabelW(lpstr
, szPath
);
518 SetWindowLong( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
541 PROCESS_INFORMATION pi
;
542 WCHAR szPath
[MAX_PATH
+ 10];
543 WCHAR szArg
[MAX_PATH
];
545 LPPROPSHEETPAGEW ppsp
;
547 FORMAT_DRIVE_CONTEXT Context
;
552 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
553 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)ppsp
->lParam
);
556 ZeroMemory( &si
, sizeof(si
) );
558 ZeroMemory( &pi
, sizeof(pi
) );
560 szDrive
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
561 switch(LOWORD(wParam
))
564 if (InitializeFmifsLibrary(&Context
))
566 Context
.Drive
= szDrive
[0];
567 DialogBoxParamW(shell32_hInstance
, L
"CHKDSK_DLG", hwndDlg
, ChkDskDlg
, (LPARAM
)&Context
);
568 FreeLibrary(Context
.hLibrary
);
572 dwSize
= sizeof(szPath
);
573 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
574 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
576 RRF_RT_REG_EXPAND_SZ
,
581 swprintf(szArg
, szPath
, szDrive
[0]);
582 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
584 szDrive
= PathAddBackslashW(szPath
);
588 wcscat(szDrive
, L
"mmc.exe");
589 if (CreateProcessW(szPath
, szArg
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
591 CloseHandle(pi
.hProcess
);
592 CloseHandle(pi
.hThread
);
597 dwSize
= sizeof(szPath
);
598 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
599 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
601 RRF_RT_REG_EXPAND_SZ
,
606 if (CreateProcessW(szPath
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
608 CloseHandle(pi
.hProcess
);
609 CloseHandle(pi
.hThread
);
628 Guids
[0] = GUID_DEVCLASS_DISKDRIVE
;
630 UNREFERENCED_PARAMETER(lParam
);
631 UNREFERENCED_PARAMETER(wParam
);
636 /* create the hardware page */
637 DeviceCreateHardwarePageEx(hwndDlg
,
639 sizeof(Guids
) / sizeof(Guids
[0]),
655 { "DRIVE_GENERAL_DLG", DriveGeneralDlg
},
656 { "DRIVE_EXTRA_DLG", DriveExtraDlg
},
657 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg
},
662 AddPropSheetPageProc(HPROPSHEETPAGE hpage
, LPARAM lParam
)
664 PROPSHEETHEADER
*ppsh
= (PROPSHEETHEADER
*)lParam
;
665 if (ppsh
!= NULL
&& ppsh
->nPages
< MAX_PROPERTY_SHEET_PAGE
)
667 ppsh
->phpage
[ppsh
->nPages
++] = hpage
;
674 SH_ShowDriveProperties(WCHAR
* drive
, LPCITEMIDLIST pidlFolder
, LPCITEMIDLIST
* apidl
)
677 HPROPSHEETPAGE hpsp
[MAX_PROPERTY_SHEET_PAGE
];
678 PROPSHEETHEADERW psh
;
681 WCHAR szName
[MAX_PATH
];
682 DWORD dwMaxComponent
, dwFileSysFlags
;
683 IDataObject
* pDataObj
= NULL
;
685 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
686 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
687 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
688 psh
.hwndParent
= NULL
;
693 if (GetVolumeInformationW(drive
, szName
, sizeof(szName
)/sizeof(WCHAR
), NULL
, &dwMaxComponent
,
694 &dwFileSysFlags
, NULL
, 0))
696 psh
.pszCaption
= szName
;
697 psh
.dwFlags
|= PSH_PROPTITLE
;
701 * check if disk is a really a local hdd
703 i
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szName
, sizeof(szName
)/sizeof(WCHAR
));
704 if (i
> 0 && i
< (sizeof(szName
)/sizeof(WCHAR
)) + 6)
708 wcscpy(&szName
[i
+2], drive
);
715 for (i
= 0; i
< DRIVE_PROPERTY_PAGES
; i
++)
717 HPROPSHEETPAGE hprop
= SH_CreatePropertySheetPage(PropPages
[i
].resname
, PropPages
[i
].dlgproc
, (LPARAM
)drive
, NULL
);
720 hpsp
[psh
.nPages
] = hprop
;
724 if (SHCreateDataObject(pidlFolder
, 1, apidl
, NULL
, &IID_IDataObject
, (void**)&pDataObj
) == S_OK
)
726 hpsx
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, L
"Drive", MAX_PROPERTY_SHEET_PAGE
-DRIVE_PROPERTY_PAGES
, pDataObj
);
729 SHAddFromPropSheetExtArray(hpsx
, (LPFNADDPROPSHEETPAGE
)AddPropSheetPageProc
, (LPARAM
)&psh
);
733 ret
= PropertySheetW(&psh
);
735 IDataObject_Release(pDataObj
);
738 SHDestroyPropSheetExtArray(hpsx
);
747 GetDefaultClusterSize(LPWSTR szFs
, PDWORD pClusterSize
, PULARGE_INTEGER TotalNumberOfBytes
)
751 if (!wcsicmp(szFs
, L
"FAT16") ||
752 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
754 if (TotalNumberOfBytes
->QuadPart
<= (16 * 1024 * 1024))
756 else if (TotalNumberOfBytes
->QuadPart
<= (32 * 1024 * 1024))
758 else if (TotalNumberOfBytes
->QuadPart
<= (64 * 1024 * 1024))
760 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
762 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
764 else if (TotalNumberOfBytes
->QuadPart
<= (512 * 1024 * 1024))
766 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
768 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
770 else if (TotalNumberOfBytes
->QuadPart
<= (4096LL * 1024LL * 1024LL))
775 else if (!wcsicmp(szFs
, L
"FAT32"))
777 if (TotalNumberOfBytes
->QuadPart
<=(64 * 1024 * 1024))
779 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
781 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
783 else if (TotalNumberOfBytes
->QuadPart
<= (8192LL * 1024LL * 1024LL))
785 else if (TotalNumberOfBytes
->QuadPart
<= (16384LL * 1024LL * 1024LL))
787 else if (TotalNumberOfBytes
->QuadPart
<= (32768LL * 1024LL * 1024LL))
792 else if (!wcsicmp(szFs
, L
"NTFS"))
794 if (TotalNumberOfBytes
->QuadPart
<=(512 * 1024 * 1024))
796 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
798 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
806 *pClusterSize
= ClusterSize
;
812 InsertDefaultClusterSizeForFs(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
814 WCHAR szFs
[100] = {0};
815 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
817 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
822 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
823 iSelIndex
= SendMessage(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
824 if (iSelIndex
== CB_ERR
)
827 if (SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFs
) == CB_ERR
)
830 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
831 szDrive
[0] = pContext
->Drive
+ 'A';
833 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
836 if (!wcsicmp(szFs
, L
"FAT16") ||
837 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
839 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
841 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes
.QuadPart
);
842 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
846 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
848 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
849 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
850 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
851 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
852 if (lIndex
!= CB_ERR
)
853 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
854 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
857 else if (!wcsicmp(szFs
, L
"FAT32"))
859 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
861 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes
.QuadPart
);
862 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
866 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
868 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
869 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
870 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
871 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
872 if (lIndex
!= CB_ERR
)
873 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
874 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
877 else if (!wcsicmp(szFs
, L
"NTFS"))
879 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
881 TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes
.QuadPart
);
882 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
886 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
887 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
889 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
890 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
891 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
892 if (lIndex
!= CB_ERR
)
893 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
894 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
897 for (lIndex
= 0; lIndex
< 4; lIndex
++)
899 TotalNumberOfBytes
.QuadPart
= ClusterSize
;
900 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
902 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
903 if (lIndex
!= CB_ERR
)
904 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
911 FIXME("unknown fs\n");
912 SendDlgItemMessageW(hwndDlg
, 28680, CB_RESETCONTENT
, iSelIndex
, 0);
918 InitializeFormatDriveDlg(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
921 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
922 WCHAR szFs
[30] = {0};
923 INT Length
, TempLength
;
924 DWORD dwSerial
, dwMaxComp
, dwFileSys
;
925 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
926 DWORD dwIndex
, dwDefault
;
927 UCHAR uMinor
, uMajor
;
931 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
932 szDrive
[0] = pContext
->Drive
+ L
'A';
933 if (GetVolumeInformationW(szDrive
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2, &dwSerial
, &dwMaxComp
, &dwFileSys
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
935 szText
[Length
] = L
' ';
936 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
937 TempLength
= wcslen(&szText
[Length
+1]);
940 /* load default volume label */
941 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
945 /* set volume label */
946 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
947 SendDlgItemMessageW(hwndDlg
, 28679, WM_SETTEXT
, 0, (LPARAM
)&szText
[Length
+1]);
949 Length
+= TempLength
+ 1;
952 if (Length
+ 4 < (sizeof(szText
)/sizeof(WCHAR
)))
954 szText
[Length
] = L
' ';
955 szText
[Length
+1] = L
'(';
956 szText
[Length
+2] = szDrive
[0];
957 szText
[Length
+3] = L
')';
961 if (Length
< (sizeof(szText
)/sizeof(WCHAR
)))
962 szText
[Length
] = L
'\0';
964 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
966 /* set window text */
967 SetWindowTextW(hwndDlg
, szText
);
969 if (GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
971 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szText
, sizeof(szText
)/sizeof(WCHAR
)))
973 /* add drive capacity */
974 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
975 SendDlgItemMessageW(hwndDlg
, 28673, CB_ADDSTRING
, 0, (LPARAM
)szText
);
976 SendDlgItemMessageW(hwndDlg
, 28673, CB_SETCURSEL
, 0, (LPARAM
)0);
980 if (pContext
->Options
& SHFMT_OPT_FULL
)
982 /* check quick format button */
983 SendDlgItemMessageW(hwndDlg
, 28674, BM_SETCHECK
, BST_CHECKED
, 0);
986 /* enumerate all available filesystems */
989 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
991 while(pContext
->QueryAvailableFileSystemFormat(dwIndex
, szText
, &uMajor
, &uMinor
, &Latest
))
993 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
994 if (!wcsicmp(szText
, szFs
))
997 SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szText
);
1003 ERR("no filesystem providers\n");
1007 /* select default filesys */
1008 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, dwDefault
, 0);
1009 /* setup cluster combo */
1010 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
1011 /* hide progress control */
1012 ShowWindow(GetDlgItem(hwndDlg
, 28678), SW_HIDE
);
1015 HWND FormatDrvDialog
= NULL
;
1016 BOOLEAN bSuccess
= FALSE
;
1022 IN CALLBACKCOMMAND Command
,
1024 IN PVOID ActionInfo
)
1031 Progress
= (PDWORD
)ActionInfo
;
1032 SendDlgItemMessageW(FormatDrvDialog
, 28678, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
1035 pSuccess
= (PBOOLEAN
)ActionInfo
;
1036 bSuccess
= (*pSuccess
);
1040 case INSUFFICIENTRIGHTS
:
1041 case FSNOTSUPPORTED
:
1042 case CLUSTERSIZETOOSMALL
:
1059 FormatDrive(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
1061 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
1062 WCHAR szFileSys
[40] = {0};
1063 WCHAR szLabel
[40] = {0};
1070 /* set volume path */
1071 szDrive
[0] = pContext
->Drive
;
1073 /* get filesystem */
1074 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
1075 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1076 if (iSelIndex
== CB_ERR
)
1081 Length
= SendMessageW(hDlgCtrl
, CB_GETLBTEXTLEN
, iSelIndex
, 0);
1082 if (Length
== CB_ERR
|| Length
+ 1> sizeof(szFileSys
)/sizeof(WCHAR
))
1088 /* retrieve the file system */
1089 SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFileSys
);
1090 szFileSys
[(sizeof(szFileSys
)/sizeof(WCHAR
))-1] = L
'\0';
1092 /* retrieve the volume label */
1093 hDlgCtrl
= GetWindow(hwndDlg
, 28679);
1094 Length
= SendMessageW(hDlgCtrl
, WM_GETTEXTLENGTH
, 0, 0);
1095 if (Length
+ 1 > sizeof(szLabel
)/sizeof(WCHAR
))
1100 SendMessageW(hDlgCtrl
, WM_GETTEXT
, sizeof(szLabel
)/sizeof(WCHAR
), (LPARAM
)szLabel
);
1101 szLabel
[(sizeof(szLabel
)/sizeof(WCHAR
))-1] = L
'\0';
1103 /* check for quickformat */
1104 if (SendDlgItemMessageW(hwndDlg
, 28674, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1107 QuickFormat
= FALSE
;
1109 /* get the cluster size */
1110 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1111 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1112 if (iSelIndex
== CB_ERR
)
1117 ClusterSize
= SendMessageW(hDlgCtrl
, CB_GETITEMDATA
, iSelIndex
, 0);
1118 if (ClusterSize
== CB_ERR
)
1124 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1125 ShowWindow(hDlgCtrl
, SW_SHOW
);
1126 SendMessageW(hDlgCtrl
, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
1130 * will cause display problems
1131 * when performing more than one format
1133 FormatDrvDialog
= hwndDlg
;
1135 pContext
->FormatEx(szDrive
,
1136 FMIFS_HARDDISK
, /* FIXME */
1143 ShowWindow(hDlgCtrl
, SW_HIDE
);
1144 FormatDrvDialog
= NULL
;
1147 pContext
->Result
= SHFMT_ERROR
;
1149 else if (QuickFormat
)
1151 pContext
->Result
= SHFMT_OPT_FULL
;
1155 pContext
->Result
= FALSE
;
1162 FormatDriveDlg(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1164 PFORMAT_DRIVE_CONTEXT pContext
;
1169 InitializeFormatDriveDlg(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
1170 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
1173 switch(LOWORD(wParam
))
1176 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1177 FormatDrive(hwndDlg
, pContext
);
1180 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1181 EndDialog(hwndDlg
, pContext
->Result
);
1183 case 28677: // filesystem combo
1184 if (HIWORD(wParam
) == CBN_SELENDOK
)
1186 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1187 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
1197 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
)
1199 INITIALIZE_FMIFS InitFmifs
;
1203 hLibrary
= pContext
->hLibrary
= LoadLibraryW(L
"fmifs.dll");
1206 ERR("failed to load fmifs.dll\n");
1210 InitFmifs
= (INITIALIZE_FMIFS
)GetProcAddress(hLibrary
, "InitializeFmIfs");
1213 ERR("InitializeFmIfs export is missing\n");
1214 FreeLibrary(hLibrary
);
1218 ret
= (*InitFmifs
)(NULL
, DLL_PROCESS_ATTACH
, NULL
);
1221 ERR("fmifs failed to initialize\n");
1222 FreeLibrary(hLibrary
);
1226 pContext
->QueryAvailableFileSystemFormat
= (QUERY_AVAILABLEFSFORMAT
)GetProcAddress(hLibrary
, "QueryAvailableFileSystemFormat");
1227 if (!pContext
->QueryAvailableFileSystemFormat
)
1229 ERR("QueryAvailableFileSystemFormat export is missing\n");
1230 FreeLibrary(hLibrary
);
1234 pContext
->FormatEx
= (FORMAT_EX
) GetProcAddress(hLibrary
, "FormatEx");
1235 if (!pContext
->FormatEx
)
1237 ERR("FormatEx export is missing\n");
1238 FreeLibrary(hLibrary
);
1242 pContext
->EnableVolumeCompression
= (ENABLEVOLUMECOMPRESSION
) GetProcAddress(hLibrary
, "EnableVolumeCompression");
1243 if (!pContext
->FormatEx
)
1245 ERR("EnableVolumeCompression export is missing\n");
1246 FreeLibrary(hLibrary
);
1250 pContext
->Chkdsk
= (CHKDSK
) GetProcAddress(hLibrary
, "Chkdsk");
1251 if (!pContext
->Chkdsk
)
1253 ERR("Chkdsk export is missing\n");
1254 FreeLibrary(hLibrary
);
1261 /*************************************************************************
1262 * SHFormatDrive (SHELL32.@)
1267 SHFormatDrive(HWND hwnd
, UINT drive
, UINT fmtID
, UINT options
)
1269 FORMAT_DRIVE_CONTEXT Context
;
1272 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd
, drive
, fmtID
, options
);
1274 if (!InitializeFmifsLibrary(&Context
))
1276 ERR("failed to initialize fmifs\n");
1277 return SHFMT_NOFORMAT
;
1280 Context
.Drive
= drive
;
1281 Context
.Options
= options
;
1283 result
= DialogBoxParamW(shell32_hInstance
, L
"FORMAT_DLG", hwnd
, FormatDriveDlg
, (LPARAM
)&Context
);
1285 FreeLibrary(Context
.hLibrary
);