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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #define MAX_PROPERTY_SHEET_PAGE 32
23 #define WIN32_NO_STATUS
24 #define NTOS_MODE_USER
29 #include <ndk/ntndk.h>
30 #include <fmifs/fmifs.h>
35 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
39 HWPD_STANDARDLIST
= 0,
41 HWPD_MAX
= HWPD_LARGELIST
42 } HWPAGE_DISPLAYMODE
, *PHWPAGE_DISPLAYMODE
;
46 (NTAPI
*INITIALIZE_FMIFS
)(
53 (NTAPI
*QUERY_AVAILABLEFSFORMAT
)(
55 IN OUT PWCHAR FileSystem
,
58 OUT BOOLEAN
* LastestVersion
62 (NTAPI
*ENABLEVOLUMECOMPRESSION
)(
71 IN FMIFS_MEDIA_FLAG MediaFlag
,
74 IN BOOLEAN QuickFormat
,
76 IN PFMIFSCALLBACK Callback
84 IN BOOLEAN CorrectErrors
,
86 IN BOOLEAN CheckOnlyIfDirty
,
90 IN PFMIFSCALLBACK Callback
99 QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat
;
101 ENABLEVOLUMECOMPRESSION EnableVolumeCompression
;
104 }FORMAT_DRIVE_CONTEXT
, *PFORMAT_DRIVE_CONTEXT
;
106 BOOL
InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
);
107 BOOL
GetDefaultClusterSize(LPWSTR szFs
, PDWORD pClusterSize
, PULARGE_INTEGER TotalNumberOfBytes
);
108 HPSXA WINAPI
SHCreatePropSheetExtArrayEx(HKEY hKey
, LPCWSTR pszSubKey
, UINT max_iface
, IDataObject
*pDataObj
);
110 DeviceCreateHardwarePageEx(HWND hWndParent
,
113 HWPAGE_DISPLAYMODE DisplayMode
);
115 HPROPSHEETPAGE
SH_CreatePropertySheetPage(LPSTR resname
, DLGPROC dlgproc
, LPARAM lParam
, LPWSTR szTitle
);
117 #define DRIVE_PROPERTY_PAGES (3)
119 static const GUID GUID_DEVCLASS_DISKDRIVE
= {0x4d36e967L
, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
123 GetDriveNameWithLetter(LPWSTR szText
, UINT Length
, WCHAR Drive
)
125 WCHAR szDrive
[] = {'C',':','\\', 0};
126 DWORD dwMaxComp
, dwFileSys
, TempLength
= 0;
129 if (GetVolumeInformationW(szDrive
, szText
, Length
, NULL
, &dwMaxComp
, &dwFileSys
, NULL
, 0))
131 szText
[Length
-1] = L
'\0';
132 TempLength
= wcslen(szText
);
135 /* load default volume label */
136 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
139 if (TempLength
+ 4 < Length
)
141 szText
[TempLength
] = L
' ';
142 szText
[TempLength
+1] = L
'(';
143 szText
[TempLength
+2] = szDrive
[0];
144 szText
[TempLength
+3] = L
')';
148 if (TempLength
< Length
)
149 szText
[TempLength
] = L
'\0';
151 szText
[Length
-1] = L
'\0';
156 InitializeChkDskDialog(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
160 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (INT_PTR
)pContext
);
162 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
164 GetDriveNameWithLetter(&szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))-Length
-1, pContext
->Drive
);
165 szText
[Length
] = L
' ';
166 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
167 SetWindowText(hwndDlg
, szText
);
170 HWND ChkdskDrvDialog
= NULL
;
171 BOOLEAN bChkdskSuccess
= FALSE
;
176 IN CALLBACKCOMMAND Command
,
185 Progress
= (PDWORD
)ActionInfo
;
186 SendDlgItemMessageW(ChkdskDrvDialog
, 14002, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
189 pSuccess
= (PBOOLEAN
)ActionInfo
;
190 bChkdskSuccess
= (*pSuccess
);
194 case INSUFFICIENTRIGHTS
:
196 case CLUSTERSIZETOOSMALL
:
197 bChkdskSuccess
= FALSE
;
209 ChkDskNow(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
211 DWORD ClusterSize
= 0, dwMaxComponentLength
, FileSystemFlags
;
213 WCHAR szDrive
[] = {'C',':','\\', 0};
214 WCHAR szVolumeLabel
[40];
215 ULARGE_INTEGER TotalNumberOfFreeBytes
, FreeBytesAvailableUser
;
216 BOOLEAN bCorrectErrors
= FALSE
, bScanDrive
= FALSE
;
218 szDrive
[0] = pContext
->Drive
;
219 if(!GetVolumeInformationW(szDrive
, szVolumeLabel
, sizeof(szVolumeLabel
)/sizeof(WCHAR
), NULL
, &dwMaxComponentLength
, &FileSystemFlags
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
221 FIXME("failed to get drive fs type\n");
225 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfFreeBytes
, NULL
))
227 FIXME("failed to get drive space type\n");
231 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfFreeBytes
))
233 FIXME("invalid cluster size\n");
237 if (SendDlgItemMessageW(hwndDlg
, 14000, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
238 bCorrectErrors
= TRUE
;
240 if (SendDlgItemMessageW(hwndDlg
, 14001, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
243 ChkdskDrvDialog
= hwndDlg
;
244 bChkdskSuccess
= FALSE
;
245 SendDlgItemMessageW(hwndDlg
, 14002, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
246 pContext
->Chkdsk(szDrive
, szFs
, bCorrectErrors
, TRUE
, FALSE
, bScanDrive
, NULL
, NULL
, ChkdskCallback
);
248 ChkdskDrvDialog
= NULL
;
249 pContext
->Result
= bChkdskSuccess
;
250 bChkdskSuccess
= FALSE
;
263 PFORMAT_DRIVE_CONTEXT pContext
;
267 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
268 InitializeChkDskDialog(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
271 switch(LOWORD(wParam
))
274 EndDialog(hwndDlg
, 0);
277 pContext
= (PFORMAT_DRIVE_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
278 ChkDskNow(hwndDlg
, pContext
);
290 GetFreeBytesShare(ULONGLONG TotalNumberOfFreeBytes
, ULONGLONG TotalNumberOfBytes
)
294 if (TotalNumberOfFreeBytes
== 0LL)
299 Temp
= TotalNumberOfBytes
/ 100;
300 if (Temp
>= TotalNumberOfFreeBytes
)
306 return TotalNumberOfFreeBytes
/ Temp
;
312 PaintStaticControls(HWND hwndDlg
, LPDRAWITEMSTRUCT drawItem
)
316 if (drawItem
->CtlID
== 14013)
318 hBrush
= CreateSolidBrush(RGB(0, 0, 255));
321 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
322 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)
343 hBlueBrush
= CreateSolidBrush(RGB(0, 0, 255));
344 hMagBrush
= CreateSolidBrush(RGB(255, 0, 255));
346 SendDlgItemMessageW(hwndDlg
, 14006, WM_GETTEXT
, 20, (LPARAM
)szBuffer
);
347 Result
= _wtoi(szBuffer
);
349 CopyRect(&rect
, &drawItem
->rcItem
);
350 horzsize
= rect
.right
- rect
.left
;
351 Result
= (Result
* horzsize
) / 100;
353 rect
.right
= drawItem
->rcItem
.right
- Result
;
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
, 14000, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szVolumeName
);
385 /* set filesystem type */
386 SendDlgItemMessageW(hwndDlg
, 14002, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)FileSystemName
);
390 DriveType
= GetDriveTypeW(szDrive
);
391 if (DriveType
== DRIVE_FIXED
|| DriveType
== DRIVE_CDROM
)
394 if(GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailable
, (PULARGE_INTEGER
)&TotalNumberOfBytes
, (PULARGE_INTEGER
)&TotalNumberOfFreeBytes
))
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
, 14007, 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
, 14007, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
418 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
- FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
419 SendDlgItemMessageW(hwndDlg
, 14003, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
421 if (StrFormatByteSizeW(FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
422 SendDlgItemMessageW(hwndDlg
, 14005, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
424 Result
= GetFreeBytesShare(TotalNumberOfFreeBytes
.QuadPart
, TotalNumberOfBytes
.QuadPart
);
425 /* set free bytes percentage */
426 swprintf(szResult
, L
"%02d%%", Result
);
427 SendDlgItemMessageW(hwndDlg
, 14006, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
428 /* store used share amount */
429 Result
= 100 - Result
;
430 swprintf(szResult
, L
"%02d%%", Result
);
431 SendDlgItemMessageW(hwndDlg
, 14004, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
432 if (DriveType
== DRIVE_FIXED
)
434 if (LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
435 SendDlgItemMessageW(hwndDlg
, 14001, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szBuffer
);
437 else /* DriveType == DRIVE_CDROM) */
439 if (LoadStringW(shell32_hInstance
, IDS_DRIVE_CDROM
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
440 SendDlgItemMessageW(hwndDlg
, 14001, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szBuffer
);
444 /* set drive description */
445 SendDlgItemMessageW(hwndDlg
, 14009, WM_GETTEXT
, (WPARAM
)50, (LPARAM
)szFormat
);
446 swprintf(szBuffer
, szFormat
, szDrive
);
447 SendDlgItemMessageW(hwndDlg
, 14009, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szBuffer
);
460 LPPROPSHEETPAGEW ppsp
;
461 LPDRAWITEMSTRUCT drawItem
;
463 PROCESS_INFORMATION pi
;
465 WCHAR szPath
[MAX_PATH
];
472 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
475 lpstr
= (WCHAR
*)ppsp
->lParam
;
476 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lpstr
);
477 InitializeGeneralDriveDialog(hwndDlg
, lpstr
);
480 drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
481 if (drawItem
->CtlID
>= 14013 && drawItem
->CtlID
<= 14015)
483 PaintStaticControls(hwndDlg
, drawItem
);
488 if (LOWORD(wParam
) == 14010) /* Disk Cleanup */
490 lpstr
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
491 ZeroMemory( &si
, sizeof(si
) );
493 ZeroMemory( &pi
, sizeof(pi
) );
494 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
496 wcscat(szPath
, L
"\\cleanmgr.exe /D ");
497 length
= wcslen(szPath
);
498 szPath
[length
] = lpstr
[0];
499 szPath
[length
+1] = L
'\0';
500 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
502 CloseHandle(pi
.hProcess
);
503 CloseHandle(pi
.hThread
);
508 lppsn
= (LPPSHNOTIFY
) lParam
;
509 if (LOWORD(wParam
) == 14000)
511 if (HIWORD(wParam
) == EN_CHANGE
)
513 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
517 if (lppsn
->hdr
.code
== PSN_APPLY
)
519 lpstr
= (LPWSTR
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
520 if (lpstr
&& SendDlgItemMessageW(hwndDlg
, 14000, WM_GETTEXT
, sizeof(szPath
)/sizeof(WCHAR
), (LPARAM
)szPath
))
522 szPath
[(sizeof(szPath
)/sizeof(WCHAR
))-1] = L
'\0';
523 SetVolumeLabelW(lpstr
, szPath
);
525 SetWindowLongPtr( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
548 PROCESS_INFORMATION pi
;
549 WCHAR szPath
[MAX_PATH
+ 10];
550 WCHAR szArg
[MAX_PATH
];
552 LPPROPSHEETPAGEW ppsp
;
554 FORMAT_DRIVE_CONTEXT Context
;
559 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
560 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)ppsp
->lParam
);
563 ZeroMemory( &si
, sizeof(si
) );
565 ZeroMemory( &pi
, sizeof(pi
) );
567 szDrive
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
568 switch(LOWORD(wParam
))
571 if (InitializeFmifsLibrary(&Context
))
573 Context
.Drive
= szDrive
[0];
574 DialogBoxParamW(shell32_hInstance
, L
"CHKDSK_DLG", hwndDlg
, ChkDskDlg
, (LPARAM
)&Context
);
575 FreeLibrary(Context
.hLibrary
);
579 dwSize
= sizeof(szPath
);
580 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
581 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
583 RRF_RT_REG_EXPAND_SZ
,
588 swprintf(szArg
, szPath
, szDrive
[0]);
589 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
591 szDrive
= PathAddBackslashW(szPath
);
595 wcscat(szDrive
, L
"mmc.exe");
596 if (CreateProcessW(szPath
, szArg
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
598 CloseHandle(pi
.hProcess
);
599 CloseHandle(pi
.hThread
);
604 dwSize
= sizeof(szPath
);
605 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
606 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
608 RRF_RT_REG_EXPAND_SZ
,
613 if (CreateProcessW(szPath
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
615 CloseHandle(pi
.hProcess
);
616 CloseHandle(pi
.hThread
);
635 Guids
[0] = GUID_DEVCLASS_DISKDRIVE
;
637 UNREFERENCED_PARAMETER(lParam
);
638 UNREFERENCED_PARAMETER(wParam
);
643 /* create the hardware page */
644 DeviceCreateHardwarePageEx(hwndDlg
,
646 sizeof(Guids
) / sizeof(Guids
[0]),
663 { "DRIVE_GENERAL_DLG", DriveGeneralDlg
, -1},
664 { "DRIVE_EXTRA_DLG", DriveExtraDlg
, DRIVE_FIXED
},
665 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg
, -1},
670 AddPropSheetPageProc(HPROPSHEETPAGE hpage
, LPARAM lParam
)
672 PROPSHEETHEADER
*ppsh
= (PROPSHEETHEADER
*)lParam
;
673 if (ppsh
!= NULL
&& ppsh
->nPages
< MAX_PROPERTY_SHEET_PAGE
)
675 ppsh
->phpage
[ppsh
->nPages
++] = hpage
;
682 SH_ShowDriveProperties(WCHAR
* drive
, LPCITEMIDLIST pidlFolder
, LPCITEMIDLIST
* apidl
)
685 HPROPSHEETPAGE hpsp
[MAX_PROPERTY_SHEET_PAGE
];
686 PROPSHEETHEADERW psh
;
689 WCHAR szName
[MAX_PATH
+6];
690 DWORD dwMaxComponent
, dwFileSysFlags
;
691 IDataObject
* pDataObj
= NULL
;
694 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
695 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
696 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
697 psh
.hwndParent
= NULL
;
701 if (GetVolumeInformationW(drive
, szName
, sizeof(szName
)/sizeof(WCHAR
), NULL
, &dwMaxComponent
,
702 &dwFileSysFlags
, NULL
, 0))
704 psh
.pszCaption
= szName
;
705 psh
.dwFlags
|= PSH_PROPTITLE
;
709 * check if disk is a really a local hdd
711 i
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szName
, sizeof(szName
)/sizeof(WCHAR
)-6);
712 if (i
> 0 && i
< (sizeof(szName
)/sizeof(WCHAR
)) - 6)
716 wcscpy(&szName
[i
+2], drive
);
723 DriveType
= GetDriveTypeW(drive
);
724 for (i
= 0; i
< DRIVE_PROPERTY_PAGES
; i
++)
726 if (PropPages
[i
].DriveType
== (UINT
)-1 || (PropPages
[i
].DriveType
!= (UINT
)-1 && PropPages
[i
].DriveType
== DriveType
))
728 HPROPSHEETPAGE hprop
= SH_CreatePropertySheetPage(PropPages
[i
].resname
, PropPages
[i
].dlgproc
, (LPARAM
)drive
, NULL
);
731 hpsp
[psh
.nPages
] = hprop
;
737 if (SHCreateDataObject(pidlFolder
, 1, apidl
, NULL
, &IID_IDataObject
, (void**)&pDataObj
) == S_OK
)
739 hpsx
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, L
"Drive", MAX_PROPERTY_SHEET_PAGE
-DRIVE_PROPERTY_PAGES
, pDataObj
);
742 SHAddFromPropSheetExtArray(hpsx
, (LPFNADDPROPSHEETPAGE
)AddPropSheetPageProc
, (LPARAM
)&psh
);
746 ret
= PropertySheetW(&psh
);
748 IDataObject_Release(pDataObj
);
751 SHDestroyPropSheetExtArray(hpsx
);
760 GetDefaultClusterSize(LPWSTR szFs
, PDWORD pClusterSize
, PULARGE_INTEGER TotalNumberOfBytes
)
764 if (!wcsicmp(szFs
, L
"FAT16") ||
765 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
767 if (TotalNumberOfBytes
->QuadPart
<= (16 * 1024 * 1024))
769 else if (TotalNumberOfBytes
->QuadPart
<= (32 * 1024 * 1024))
771 else if (TotalNumberOfBytes
->QuadPart
<= (64 * 1024 * 1024))
773 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
775 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
777 else if (TotalNumberOfBytes
->QuadPart
<= (512 * 1024 * 1024))
779 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
781 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
783 else if (TotalNumberOfBytes
->QuadPart
<= (4096LL * 1024LL * 1024LL))
788 else if (!wcsicmp(szFs
, L
"FAT32"))
790 if (TotalNumberOfBytes
->QuadPart
<=(64 * 1024 * 1024))
792 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
794 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
796 else if (TotalNumberOfBytes
->QuadPart
<= (8192LL * 1024LL * 1024LL))
798 else if (TotalNumberOfBytes
->QuadPart
<= (16384LL * 1024LL * 1024LL))
800 else if (TotalNumberOfBytes
->QuadPart
<= (32768LL * 1024LL * 1024LL))
805 else if (!wcsicmp(szFs
, L
"NTFS"))
807 if (TotalNumberOfBytes
->QuadPart
<=(512 * 1024 * 1024))
809 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
811 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
819 *pClusterSize
= ClusterSize
;
825 InsertDefaultClusterSizeForFs(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
827 WCHAR szFs
[100] = {0};
828 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
830 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
835 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
836 iSelIndex
= SendMessage(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
837 if (iSelIndex
== CB_ERR
)
840 if (SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFs
) == CB_ERR
)
843 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
844 szDrive
[0] = pContext
->Drive
+ 'A';
846 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
849 if (!wcsicmp(szFs
, L
"FAT16") ||
850 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
852 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
854 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes
.QuadPart
);
855 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
859 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
861 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
862 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
863 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
864 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
865 if (lIndex
!= CB_ERR
)
866 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
867 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
870 else if (!wcsicmp(szFs
, L
"FAT32"))
872 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
874 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes
.QuadPart
);
875 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
879 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
881 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
882 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
883 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
884 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
885 if (lIndex
!= CB_ERR
)
886 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
887 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
890 else if (!wcsicmp(szFs
, L
"NTFS"))
892 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
894 TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes
.QuadPart
);
895 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
899 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
900 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
902 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
903 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
904 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
905 if (lIndex
!= CB_ERR
)
906 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
907 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
910 for (lIndex
= 0; lIndex
< 4; lIndex
++)
912 TotalNumberOfBytes
.QuadPart
= ClusterSize
;
913 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
915 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
916 if (lIndex
!= CB_ERR
)
917 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
924 FIXME("unknown fs\n");
925 SendDlgItemMessageW(hwndDlg
, 28680, CB_RESETCONTENT
, iSelIndex
, 0);
931 InitializeFormatDriveDlg(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
934 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
935 WCHAR szFs
[30] = {0};
936 INT Length
, TempLength
;
937 DWORD dwSerial
, dwMaxComp
, dwFileSys
;
938 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
939 DWORD dwIndex
, dwDefault
;
940 UCHAR uMinor
, uMajor
;
944 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
947 szDrive
[0] = pContext
->Drive
+ L
'A';
948 if (GetVolumeInformationW(szDrive
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2, &dwSerial
, &dwMaxComp
, &dwFileSys
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
950 szText
[Length
] = L
' ';
951 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
952 TempLength
= wcslen(&szText
[Length
+1]);
955 /* load default volume label */
956 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
960 /* set volume label */
961 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
962 SendDlgItemMessageW(hwndDlg
, 28679, WM_SETTEXT
, 0, (LPARAM
)&szText
[Length
+1]);
964 Length
+= TempLength
+ 1;
967 if (Length
+ 4 < (sizeof(szText
)/sizeof(WCHAR
)))
969 szText
[Length
] = L
' ';
970 szText
[Length
+1] = L
'(';
971 szText
[Length
+2] = szDrive
[0];
972 szText
[Length
+3] = L
')';
976 if (Length
< (sizeof(szText
)/sizeof(WCHAR
)))
977 szText
[Length
] = L
'\0';
979 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
981 /* set window text */
982 SetWindowTextW(hwndDlg
, szText
);
984 if (GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
986 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szText
, sizeof(szText
)/sizeof(WCHAR
)))
988 /* add drive capacity */
989 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
990 SendDlgItemMessageW(hwndDlg
, 28673, CB_ADDSTRING
, 0, (LPARAM
)szText
);
991 SendDlgItemMessageW(hwndDlg
, 28673, CB_SETCURSEL
, 0, (LPARAM
)0);
995 if (pContext
->Options
& SHFMT_OPT_FULL
)
997 /* check quick format button */
998 SendDlgItemMessageW(hwndDlg
, 28674, BM_SETCHECK
, BST_CHECKED
, 0);
1001 /* enumerate all available filesystems */
1004 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
1006 while(pContext
->QueryAvailableFileSystemFormat(dwIndex
, szText
, &uMajor
, &uMinor
, &Latest
))
1008 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
1009 if (!wcsicmp(szText
, szFs
))
1010 dwDefault
= dwIndex
;
1012 SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szText
);
1018 ERR("no filesystem providers\n");
1022 /* select default filesys */
1023 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, dwDefault
, 0);
1024 /* setup cluster combo */
1025 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
1026 /* hide progress control */
1027 ShowWindow(GetDlgItem(hwndDlg
, 28678), SW_HIDE
);
1030 HWND FormatDrvDialog
= NULL
;
1031 BOOLEAN bSuccess
= FALSE
;
1037 IN CALLBACKCOMMAND Command
,
1039 IN PVOID ActionInfo
)
1046 Progress
= (PDWORD
)ActionInfo
;
1047 SendDlgItemMessageW(FormatDrvDialog
, 28678, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
1050 pSuccess
= (PBOOLEAN
)ActionInfo
;
1051 bSuccess
= (*pSuccess
);
1055 case INSUFFICIENTRIGHTS
:
1056 case FSNOTSUPPORTED
:
1057 case CLUSTERSIZETOOSMALL
:
1074 FormatDrive(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
1076 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
1077 WCHAR szFileSys
[40] = {0};
1078 WCHAR szLabel
[40] = {0};
1085 /* set volume path */
1086 szDrive
[0] = pContext
->Drive
;
1088 /* get filesystem */
1089 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
1090 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1091 if (iSelIndex
== CB_ERR
)
1096 Length
= SendMessageW(hDlgCtrl
, CB_GETLBTEXTLEN
, iSelIndex
, 0);
1097 if (Length
== CB_ERR
|| Length
+ 1> sizeof(szFileSys
)/sizeof(WCHAR
))
1103 /* retrieve the file system */
1104 SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFileSys
);
1105 szFileSys
[(sizeof(szFileSys
)/sizeof(WCHAR
))-1] = L
'\0';
1107 /* retrieve the volume label */
1108 hDlgCtrl
= GetWindow(hwndDlg
, 28679);
1109 Length
= SendMessageW(hDlgCtrl
, WM_GETTEXTLENGTH
, 0, 0);
1110 if (Length
+ 1 > sizeof(szLabel
)/sizeof(WCHAR
))
1115 SendMessageW(hDlgCtrl
, WM_GETTEXT
, sizeof(szLabel
)/sizeof(WCHAR
), (LPARAM
)szLabel
);
1116 szLabel
[(sizeof(szLabel
)/sizeof(WCHAR
))-1] = L
'\0';
1118 /* check for quickformat */
1119 if (SendDlgItemMessageW(hwndDlg
, 28674, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1122 QuickFormat
= FALSE
;
1124 /* get the cluster size */
1125 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1126 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1127 if (iSelIndex
== CB_ERR
)
1132 ClusterSize
= SendMessageW(hDlgCtrl
, CB_GETITEMDATA
, iSelIndex
, 0);
1133 if (ClusterSize
== CB_ERR
)
1139 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1140 ShowWindow(hDlgCtrl
, SW_SHOW
);
1141 SendMessageW(hDlgCtrl
, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
1145 * will cause display problems
1146 * when performing more than one format
1148 FormatDrvDialog
= hwndDlg
;
1150 pContext
->FormatEx(szDrive
,
1151 FMIFS_HARDDISK
, /* FIXME */
1158 ShowWindow(hDlgCtrl
, SW_HIDE
);
1159 FormatDrvDialog
= NULL
;
1162 pContext
->Result
= SHFMT_ERROR
;
1164 else if (QuickFormat
)
1166 pContext
->Result
= SHFMT_OPT_FULL
;
1170 pContext
->Result
= FALSE
;
1177 FormatDriveDlg(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1179 PFORMAT_DRIVE_CONTEXT pContext
;
1184 InitializeFormatDriveDlg(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
1185 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
1188 switch(LOWORD(wParam
))
1191 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1192 FormatDrive(hwndDlg
, pContext
);
1195 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1196 EndDialog(hwndDlg
, pContext
->Result
);
1198 case 28677: // filesystem combo
1199 if (HIWORD(wParam
) == CBN_SELENDOK
)
1201 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1202 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
1212 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
)
1214 INITIALIZE_FMIFS InitFmifs
;
1218 hLibrary
= pContext
->hLibrary
= LoadLibraryW(L
"fmifs.dll");
1221 ERR("failed to load fmifs.dll\n");
1225 InitFmifs
= (INITIALIZE_FMIFS
)GetProcAddress(hLibrary
, "InitializeFmIfs");
1228 ERR("InitializeFmIfs export is missing\n");
1229 FreeLibrary(hLibrary
);
1233 ret
= (*InitFmifs
)(NULL
, DLL_PROCESS_ATTACH
, NULL
);
1236 ERR("fmifs failed to initialize\n");
1237 FreeLibrary(hLibrary
);
1241 pContext
->QueryAvailableFileSystemFormat
= (QUERY_AVAILABLEFSFORMAT
)GetProcAddress(hLibrary
, "QueryAvailableFileSystemFormat");
1242 if (!pContext
->QueryAvailableFileSystemFormat
)
1244 ERR("QueryAvailableFileSystemFormat export is missing\n");
1245 FreeLibrary(hLibrary
);
1249 pContext
->FormatEx
= (FORMAT_EX
) GetProcAddress(hLibrary
, "FormatEx");
1250 if (!pContext
->FormatEx
)
1252 ERR("FormatEx export is missing\n");
1253 FreeLibrary(hLibrary
);
1257 pContext
->EnableVolumeCompression
= (ENABLEVOLUMECOMPRESSION
) GetProcAddress(hLibrary
, "EnableVolumeCompression");
1258 if (!pContext
->FormatEx
)
1260 ERR("EnableVolumeCompression export is missing\n");
1261 FreeLibrary(hLibrary
);
1265 pContext
->Chkdsk
= (CHKDSK
) GetProcAddress(hLibrary
, "Chkdsk");
1266 if (!pContext
->Chkdsk
)
1268 ERR("Chkdsk export is missing\n");
1269 FreeLibrary(hLibrary
);
1276 /*************************************************************************
1277 * SHFormatDrive (SHELL32.@)
1282 SHFormatDrive(HWND hwnd
, UINT drive
, UINT fmtID
, UINT options
)
1284 FORMAT_DRIVE_CONTEXT Context
;
1287 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd
, drive
, fmtID
, options
);
1289 if (!InitializeFmifsLibrary(&Context
))
1291 ERR("failed to initialize fmifs\n");
1292 return SHFMT_NOFORMAT
;
1295 Context
.Drive
= drive
;
1296 Context
.Options
= options
;
1298 result
= DialogBoxParamW(shell32_hInstance
, L
"FORMAT_DLG", hwnd
, FormatDriveDlg
, (LPARAM
)&Context
);
1300 FreeLibrary(Context
.hLibrary
);