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
20 #define MAX_PROPERTY_SHEET_PAGE 32
22 #define WIN32_NO_STATUS
23 #define NTOS_MODE_USER
28 #include <ndk/ntndk.h>
29 #include <fmifs/fmifs.h>
33 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
37 HWPD_STANDARDLIST
= 0,
39 HWPD_MAX
= HWPD_LARGELIST
40 } HWPAGE_DISPLAYMODE
, *PHWPAGE_DISPLAYMODE
;
44 (NTAPI
*INITIALIZE_FMIFS
)(
51 (NTAPI
*QUERY_AVAILABLEFSFORMAT
)(
53 IN OUT PWCHAR FileSystem
,
56 OUT BOOLEAN
* LastestVersion
60 (NTAPI
*ENABLEVOLUMECOMPRESSION
)(
69 IN FMIFS_MEDIA_FLAG MediaFlag
,
72 IN BOOLEAN QuickFormat
,
74 IN PFMIFSCALLBACK Callback
82 IN BOOLEAN CorrectErrors
,
84 IN BOOLEAN CheckOnlyIfDirty
,
88 IN PFMIFSCALLBACK Callback
97 QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat
;
99 ENABLEVOLUMECOMPRESSION EnableVolumeCompression
;
102 }FORMAT_DRIVE_CONTEXT
, *PFORMAT_DRIVE_CONTEXT
;
104 BOOL
InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
);
105 BOOL
GetDefaultClusterSize(LPWSTR szFs
, PDWORD pClusterSize
, PULARGE_INTEGER TotalNumberOfBytes
);
106 HPSXA WINAPI
SHCreatePropSheetExtArrayEx(HKEY hKey
, LPCWSTR pszSubKey
, UINT max_iface
, IDataObject
*pDataObj
);
108 DeviceCreateHardwarePageEx(HWND hWndParent
,
111 HWPAGE_DISPLAYMODE DisplayMode
);
113 HPROPSHEETPAGE
SH_CreatePropertySheetPage(LPSTR resname
, DLGPROC dlgproc
, LPARAM lParam
, LPWSTR szTitle
);
115 #define DRIVE_PROPERTY_PAGES (3)
117 static const GUID GUID_DEVCLASS_DISKDRIVE
= {0x4d36e967L
, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
121 GetDriveNameWithLetter(LPWSTR szText
, UINT Length
, WCHAR Drive
)
123 WCHAR szDrive
[] = {'C',':','\\', 0};
124 DWORD dwMaxComp
, dwFileSys
, TempLength
= 0;
127 if (GetVolumeInformationW(szDrive
, szText
, Length
, NULL
, &dwMaxComp
, &dwFileSys
, NULL
, 0))
129 szText
[Length
-1] = L
'\0';
130 TempLength
= wcslen(szText
);
133 /* load default volume label */
134 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
137 if (TempLength
+ 4 < Length
)
139 szText
[TempLength
] = L
' ';
140 szText
[TempLength
+1] = L
'(';
141 szText
[TempLength
+2] = szDrive
[0];
142 szText
[TempLength
+3] = L
')';
146 if (TempLength
< Length
)
147 szText
[TempLength
] = L
'\0';
149 szText
[Length
-1] = L
'\0';
154 InitializeChkDskDialog(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
158 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (INT_PTR
)pContext
);
160 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
162 GetDriveNameWithLetter(&szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))-Length
-1, pContext
->Drive
);
163 szText
[Length
] = L
' ';
164 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
165 SetWindowText(hwndDlg
, szText
);
168 HWND ChkdskDrvDialog
= NULL
;
169 BOOLEAN bChkdskSuccess
= FALSE
;
174 IN CALLBACKCOMMAND Command
,
183 Progress
= (PDWORD
)ActionInfo
;
184 SendDlgItemMessageW(ChkdskDrvDialog
, 14002, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
187 pSuccess
= (PBOOLEAN
)ActionInfo
;
188 bChkdskSuccess
= (*pSuccess
);
192 case INSUFFICIENTRIGHTS
:
194 case CLUSTERSIZETOOSMALL
:
195 bChkdskSuccess
= FALSE
;
207 ChkDskNow(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
209 DWORD ClusterSize
= 0, dwMaxComponentLength
, FileSystemFlags
;
211 WCHAR szDrive
[] = {'C',':','\\', 0};
212 WCHAR szVolumeLabel
[40];
213 ULARGE_INTEGER TotalNumberOfFreeBytes
, FreeBytesAvailableUser
;
214 BOOLEAN bCorrectErrors
= FALSE
, bScanDrive
= FALSE
;
216 szDrive
[0] = pContext
->Drive
;
217 if(!GetVolumeInformationW(szDrive
, szVolumeLabel
, sizeof(szVolumeLabel
)/sizeof(WCHAR
), NULL
, &dwMaxComponentLength
, &FileSystemFlags
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
219 FIXME("failed to get drive fs type\n");
223 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfFreeBytes
, NULL
))
225 FIXME("failed to get drive space type\n");
229 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfFreeBytes
))
231 FIXME("invalid cluster size\n");
235 if (SendDlgItemMessageW(hwndDlg
, 14000, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
236 bCorrectErrors
= TRUE
;
238 if (SendDlgItemMessageW(hwndDlg
, 14001, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
241 ChkdskDrvDialog
= hwndDlg
;
242 bChkdskSuccess
= FALSE
;
243 SendDlgItemMessageW(hwndDlg
, 14002, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
244 pContext
->Chkdsk(szDrive
, szFs
, bCorrectErrors
, TRUE
, FALSE
, bScanDrive
, NULL
, NULL
, ChkdskCallback
);
246 ChkdskDrvDialog
= NULL
;
247 pContext
->Result
= bChkdskSuccess
;
248 bChkdskSuccess
= FALSE
;
261 PFORMAT_DRIVE_CONTEXT pContext
;
265 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
266 InitializeChkDskDialog(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
269 switch(LOWORD(wParam
))
272 EndDialog(hwndDlg
, 0);
275 pContext
= (PFORMAT_DRIVE_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
276 ChkDskNow(hwndDlg
, pContext
);
288 GetFreeBytesShare(LARGE_INTEGER TotalNumberOfFreeBytes
, LARGE_INTEGER TotalNumberOfBytes
)
290 LARGE_INTEGER Temp
, Result
;
292 if (TotalNumberOfFreeBytes
.QuadPart
== 0LL)
298 Temp
.QuadPart
= TotalNumberOfBytes
.QuadPart
/ 100;
299 if (Temp
.QuadPart
>= TotalNumberOfFreeBytes
.QuadPart
)
304 Result
.QuadPart
= TotalNumberOfFreeBytes
.QuadPart
/ Temp
.QuadPart
;
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
);
324 }else if (drawItem
->CtlID
== 14014)
326 hBrush
= CreateSolidBrush(RGB(255, 0, 255));
329 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
330 DeleteObject((HGDIOBJ
)hBrush
);
333 else if (drawItem
->CtlID
== 14015)
339 LARGE_INTEGER Result
;
342 hBlueBrush
= CreateSolidBrush(RGB(0, 0, 255));
343 hMagBrush
= CreateSolidBrush(RGB(255, 0, 255));
345 SendDlgItemMessageW(hwndDlg
, 14007, WM_GETTEXT
, 20, (LPARAM
)szBuffer
);
346 Result
.QuadPart
= _wtoi(szBuffer
);
348 CopyRect(&rect
, &drawItem
->rcItem
);
349 horzsize
= rect
.right
- rect
.left
;
350 Result
.QuadPart
= (Result
.QuadPart
* horzsize
) / 100;
352 rect
.right
= drawItem
->rcItem
.right
- Result
.QuadPart
;
353 FillRect(drawItem
->hDC
, &rect
, hBlueBrush
);
354 rect
.left
= rect
.right
;
355 rect
.right
= drawItem
->rcItem
.right
;
356 FillRect(drawItem
->hDC
, &rect
, hMagBrush
);
357 DeleteObject(hBlueBrush
);
358 DeleteObject(hMagBrush
);
364 InitializeGeneralDriveDialog(HWND hwndDlg
, WCHAR
* szDrive
)
366 WCHAR szVolumeName
[MAX_PATH
+1] = {0};
367 DWORD MaxComponentLength
= 0;
368 DWORD FileSystemFlags
= 0;
369 WCHAR FileSystemName
[MAX_PATH
+1] = {0};
374 ULARGE_INTEGER FreeBytesAvailable
;
375 LARGE_INTEGER TotalNumberOfFreeBytes
;
376 LARGE_INTEGER TotalNumberOfBytes
;
378 ret
= GetVolumeInformationW(szDrive
, szVolumeName
, MAX_PATH
+1, NULL
, &MaxComponentLength
, &FileSystemFlags
, FileSystemName
, MAX_PATH
+1);
381 /* set volume label */
382 SendDlgItemMessageW(hwndDlg
, 14001, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szVolumeName
);
384 /* set filesystem type */
385 SendDlgItemMessageW(hwndDlg
, 14003, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)FileSystemName
);
389 DriveType
= GetDriveTypeW(szDrive
);
390 if (DriveType
== DRIVE_FIXED
|| DriveType
== DRIVE_CDROM
)
393 if(GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailable
, (PULARGE_INTEGER
)&TotalNumberOfBytes
, (PULARGE_INTEGER
)&TotalNumberOfFreeBytes
))
396 LARGE_INTEGER Result
;
397 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
399 DWORD BytesReturned
= 0;
401 swprintf(szResult
, L
"\\\\.\\%c:", towupper(szDrive
[0]));
402 hVolume
= CreateFileW(szResult
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
403 if (hVolume
!= INVALID_HANDLE_VALUE
)
405 ret
= DeviceIoControl(hVolume
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, (LPVOID
)&TotalNumberOfBytes
, sizeof(ULARGE_INTEGER
), &BytesReturned
, NULL
);
406 if (ret
&& StrFormatByteSizeW(LengthInformation
.Length
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
407 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
409 CloseHandle(hVolume
);
411 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult
), hVolume
, ret
, LengthInformation
.Length
.QuadPart
, BytesReturned
);
413 if (ret
&& StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
414 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
417 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
- FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
418 SendDlgItemMessageW(hwndDlg
, 14004, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
420 if (StrFormatByteSizeW(FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
421 SendDlgItemMessageW(hwndDlg
, 14006, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
423 Result
= GetFreeBytesShare(TotalNumberOfFreeBytes
, TotalNumberOfBytes
);
424 /* set free bytes percentage */
425 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
426 SendDlgItemMessageW(hwndDlg
, 14007, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
427 /* store used share amount */
428 Result
.QuadPart
= 100 - Result
.QuadPart
;
429 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
430 SendDlgItemMessageW(hwndDlg
, 14005, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
431 if (LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
432 SendDlgItemMessageW(hwndDlg
, 14002, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szBuffer
);
436 /* set drive description */
437 SendDlgItemMessageW(hwndDlg
, 14010, WM_GETTEXT
, (WPARAM
)50, (LPARAM
)szFormat
);
438 swprintf(szBuffer
, szFormat
, szDrive
);
439 SendDlgItemMessageW(hwndDlg
, 14010, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szBuffer
);
452 LPPROPSHEETPAGEW ppsp
;
453 LPDRAWITEMSTRUCT drawItem
;
455 PROCESS_INFORMATION pi
;
457 WCHAR szPath
[MAX_PATH
];
464 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
467 lpstr
= (WCHAR
*)ppsp
->lParam
;
468 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lpstr
);
469 InitializeGeneralDriveDialog(hwndDlg
, lpstr
);
472 drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
473 if (drawItem
->CtlID
>= 14013 && drawItem
->CtlID
<= 14015)
475 PaintStaticControls(hwndDlg
, drawItem
);
480 if (LOWORD(wParam
) == 14010) /* Disk Cleanup */
482 lpstr
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
483 ZeroMemory( &si
, sizeof(si
) );
485 ZeroMemory( &pi
, sizeof(pi
) );
486 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
488 wcscat(szPath
, L
"\\cleanmgr.exe /D ");
489 length
= wcslen(szPath
);
490 szPath
[length
] = lpstr
[0];
491 szPath
[length
+1] = L
'\0';
492 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
494 CloseHandle(pi
.hProcess
);
495 CloseHandle(pi
.hThread
);
500 lppsn
= (LPPSHNOTIFY
) lParam
;
501 if (LOWORD(wParam
) == 14000)
503 if (HIWORD(wParam
) == EN_CHANGE
)
505 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
509 if (lppsn
->hdr
.code
== PSN_APPLY
)
511 lpstr
= (LPWSTR
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
512 if (lpstr
&& SendDlgItemMessageW(hwndDlg
, 14000, WM_GETTEXT
, sizeof(szPath
)/sizeof(WCHAR
), (LPARAM
)szPath
))
514 szPath
[(sizeof(szPath
)/sizeof(WCHAR
))-1] = L
'\0';
515 SetVolumeLabelW(lpstr
, szPath
);
517 SetWindowLongPtr( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
540 PROCESS_INFORMATION pi
;
541 WCHAR szPath
[MAX_PATH
+ 10];
542 WCHAR szArg
[MAX_PATH
];
544 LPPROPSHEETPAGEW ppsp
;
546 FORMAT_DRIVE_CONTEXT Context
;
551 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
552 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)ppsp
->lParam
);
555 ZeroMemory( &si
, sizeof(si
) );
557 ZeroMemory( &pi
, sizeof(pi
) );
559 szDrive
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
560 switch(LOWORD(wParam
))
563 if (InitializeFmifsLibrary(&Context
))
565 Context
.Drive
= szDrive
[0];
566 DialogBoxParamW(shell32_hInstance
, L
"CHKDSK_DLG", hwndDlg
, ChkDskDlg
, (LPARAM
)&Context
);
567 FreeLibrary(Context
.hLibrary
);
571 dwSize
= sizeof(szPath
);
572 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
573 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
575 RRF_RT_REG_EXPAND_SZ
,
580 swprintf(szArg
, szPath
, szDrive
[0]);
581 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
583 szDrive
= PathAddBackslashW(szPath
);
587 wcscat(szDrive
, L
"mmc.exe");
588 if (CreateProcessW(szPath
, szArg
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
590 CloseHandle(pi
.hProcess
);
591 CloseHandle(pi
.hThread
);
596 dwSize
= sizeof(szPath
);
597 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
598 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
600 RRF_RT_REG_EXPAND_SZ
,
605 if (CreateProcessW(szPath
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
607 CloseHandle(pi
.hProcess
);
608 CloseHandle(pi
.hThread
);
627 Guids
[0] = GUID_DEVCLASS_DISKDRIVE
;
629 UNREFERENCED_PARAMETER(lParam
);
630 UNREFERENCED_PARAMETER(wParam
);
635 /* create the hardware page */
636 DeviceCreateHardwarePageEx(hwndDlg
,
638 sizeof(Guids
) / sizeof(Guids
[0]),
655 { "DRIVE_GENERAL_DLG", DriveGeneralDlg
, -1},
656 { "DRIVE_EXTRA_DLG", DriveExtraDlg
, DRIVE_FIXED
},
657 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg
, -1},
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
+6];
682 DWORD dwMaxComponent
, dwFileSysFlags
;
683 IDataObject
* pDataObj
= NULL
;
686 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
687 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
688 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
689 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
)-6);
704 if (i
> 0 && i
< (sizeof(szName
)/sizeof(WCHAR
)) - 6)
708 wcscpy(&szName
[i
+2], drive
);
715 DriveType
= GetDriveTypeW(drive
);
716 for (i
= 0; i
< DRIVE_PROPERTY_PAGES
; i
++)
718 if (PropPages
[i
].DriveType
== (UINT
)-1 || (PropPages
[i
].DriveType
!= (UINT
)-1 && PropPages
[i
].DriveType
== DriveType
))
720 HPROPSHEETPAGE hprop
= SH_CreatePropertySheetPage(PropPages
[i
].resname
, PropPages
[i
].dlgproc
, (LPARAM
)drive
, NULL
);
723 hpsp
[psh
.nPages
] = hprop
;
729 if (SHCreateDataObject(pidlFolder
, 1, apidl
, NULL
, &IID_IDataObject
, (void**)&pDataObj
) == S_OK
)
731 hpsx
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, L
"Drive", MAX_PROPERTY_SHEET_PAGE
-DRIVE_PROPERTY_PAGES
, pDataObj
);
734 SHAddFromPropSheetExtArray(hpsx
, (LPFNADDPROPSHEETPAGE
)AddPropSheetPageProc
, (LPARAM
)&psh
);
738 ret
= PropertySheetW(&psh
);
740 IDataObject_Release(pDataObj
);
743 SHDestroyPropSheetExtArray(hpsx
);
752 GetDefaultClusterSize(LPWSTR szFs
, PDWORD pClusterSize
, PULARGE_INTEGER TotalNumberOfBytes
)
756 if (!wcsicmp(szFs
, L
"FAT16") ||
757 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
759 if (TotalNumberOfBytes
->QuadPart
<= (16 * 1024 * 1024))
761 else if (TotalNumberOfBytes
->QuadPart
<= (32 * 1024 * 1024))
763 else if (TotalNumberOfBytes
->QuadPart
<= (64 * 1024 * 1024))
765 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
767 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
769 else if (TotalNumberOfBytes
->QuadPart
<= (512 * 1024 * 1024))
771 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
773 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
775 else if (TotalNumberOfBytes
->QuadPart
<= (4096LL * 1024LL * 1024LL))
780 else if (!wcsicmp(szFs
, L
"FAT32"))
782 if (TotalNumberOfBytes
->QuadPart
<=(64 * 1024 * 1024))
784 else if (TotalNumberOfBytes
->QuadPart
<= (128 * 1024 * 1024))
786 else if (TotalNumberOfBytes
->QuadPart
<= (256 * 1024 * 1024))
788 else if (TotalNumberOfBytes
->QuadPart
<= (8192LL * 1024LL * 1024LL))
790 else if (TotalNumberOfBytes
->QuadPart
<= (16384LL * 1024LL * 1024LL))
792 else if (TotalNumberOfBytes
->QuadPart
<= (32768LL * 1024LL * 1024LL))
797 else if (!wcsicmp(szFs
, L
"NTFS"))
799 if (TotalNumberOfBytes
->QuadPart
<=(512 * 1024 * 1024))
801 else if (TotalNumberOfBytes
->QuadPart
<= (1024 * 1024 * 1024))
803 else if (TotalNumberOfBytes
->QuadPart
<= (2048LL * 1024LL * 1024LL))
811 *pClusterSize
= ClusterSize
;
817 InsertDefaultClusterSizeForFs(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
819 WCHAR szFs
[100] = {0};
820 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
822 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
827 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
828 iSelIndex
= SendMessage(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
829 if (iSelIndex
== CB_ERR
)
832 if (SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFs
) == CB_ERR
)
835 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
836 szDrive
[0] = pContext
->Drive
+ 'A';
838 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
841 if (!wcsicmp(szFs
, L
"FAT16") ||
842 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
844 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
846 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes
.QuadPart
);
847 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
851 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
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);
862 else if (!wcsicmp(szFs
, L
"FAT32"))
864 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
866 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes
.QuadPart
);
867 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
871 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
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);
882 else if (!wcsicmp(szFs
, L
"NTFS"))
884 if (!GetDefaultClusterSize(szFs
, &ClusterSize
, &TotalNumberOfBytes
))
886 TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes
.QuadPart
);
887 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
891 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
892 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
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);
902 for (lIndex
= 0; lIndex
< 4; lIndex
++)
904 TotalNumberOfBytes
.QuadPart
= ClusterSize
;
905 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
907 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
908 if (lIndex
!= CB_ERR
)
909 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
916 FIXME("unknown fs\n");
917 SendDlgItemMessageW(hwndDlg
, 28680, CB_RESETCONTENT
, iSelIndex
, 0);
923 InitializeFormatDriveDlg(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
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
;
936 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
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
)))
942 szText
[Length
] = L
' ';
943 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
944 TempLength
= wcslen(&szText
[Length
+1]);
947 /* load default volume label */
948 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
952 /* set volume label */
953 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
954 SendDlgItemMessageW(hwndDlg
, 28679, WM_SETTEXT
, 0, (LPARAM
)&szText
[Length
+1]);
956 Length
+= TempLength
+ 1;
959 if (Length
+ 4 < (sizeof(szText
)/sizeof(WCHAR
)))
961 szText
[Length
] = L
' ';
962 szText
[Length
+1] = L
'(';
963 szText
[Length
+2] = szDrive
[0];
964 szText
[Length
+3] = L
')';
968 if (Length
< (sizeof(szText
)/sizeof(WCHAR
)))
969 szText
[Length
] = L
'\0';
971 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
973 /* set window text */
974 SetWindowTextW(hwndDlg
, szText
);
976 if (GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
978 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szText
, sizeof(szText
)/sizeof(WCHAR
)))
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);
987 if (pContext
->Options
& SHFMT_OPT_FULL
)
989 /* check quick format button */
990 SendDlgItemMessageW(hwndDlg
, 28674, BM_SETCHECK
, BST_CHECKED
, 0);
993 /* enumerate all available filesystems */
996 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
998 while(pContext
->QueryAvailableFileSystemFormat(dwIndex
, szText
, &uMajor
, &uMinor
, &Latest
))
1000 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
1001 if (!wcsicmp(szText
, szFs
))
1002 dwDefault
= dwIndex
;
1004 SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szText
);
1010 ERR("no filesystem providers\n");
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
);
1022 HWND FormatDrvDialog
= NULL
;
1023 BOOLEAN bSuccess
= FALSE
;
1029 IN CALLBACKCOMMAND Command
,
1031 IN PVOID ActionInfo
)
1038 Progress
= (PDWORD
)ActionInfo
;
1039 SendDlgItemMessageW(FormatDrvDialog
, 28678, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
1042 pSuccess
= (PBOOLEAN
)ActionInfo
;
1043 bSuccess
= (*pSuccess
);
1047 case INSUFFICIENTRIGHTS
:
1048 case FSNOTSUPPORTED
:
1049 case CLUSTERSIZETOOSMALL
:
1066 FormatDrive(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
1068 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
1069 WCHAR szFileSys
[40] = {0};
1070 WCHAR szLabel
[40] = {0};
1077 /* set volume path */
1078 szDrive
[0] = pContext
->Drive
;
1080 /* get filesystem */
1081 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
1082 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1083 if (iSelIndex
== CB_ERR
)
1088 Length
= SendMessageW(hDlgCtrl
, CB_GETLBTEXTLEN
, iSelIndex
, 0);
1089 if (Length
== CB_ERR
|| Length
+ 1> sizeof(szFileSys
)/sizeof(WCHAR
))
1095 /* retrieve the file system */
1096 SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFileSys
);
1097 szFileSys
[(sizeof(szFileSys
)/sizeof(WCHAR
))-1] = L
'\0';
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
))
1107 SendMessageW(hDlgCtrl
, WM_GETTEXT
, sizeof(szLabel
)/sizeof(WCHAR
), (LPARAM
)szLabel
);
1108 szLabel
[(sizeof(szLabel
)/sizeof(WCHAR
))-1] = L
'\0';
1110 /* check for quickformat */
1111 if (SendDlgItemMessageW(hwndDlg
, 28674, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1114 QuickFormat
= FALSE
;
1116 /* get the cluster size */
1117 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1118 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
1119 if (iSelIndex
== CB_ERR
)
1124 ClusterSize
= SendMessageW(hDlgCtrl
, CB_GETITEMDATA
, iSelIndex
, 0);
1125 if (ClusterSize
== CB_ERR
)
1131 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
1132 ShowWindow(hDlgCtrl
, SW_SHOW
);
1133 SendMessageW(hDlgCtrl
, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
1137 * will cause display problems
1138 * when performing more than one format
1140 FormatDrvDialog
= hwndDlg
;
1142 pContext
->FormatEx(szDrive
,
1143 FMIFS_HARDDISK
, /* FIXME */
1150 ShowWindow(hDlgCtrl
, SW_HIDE
);
1151 FormatDrvDialog
= NULL
;
1154 pContext
->Result
= SHFMT_ERROR
;
1156 else if (QuickFormat
)
1158 pContext
->Result
= SHFMT_OPT_FULL
;
1162 pContext
->Result
= FALSE
;
1169 FormatDriveDlg(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1171 PFORMAT_DRIVE_CONTEXT pContext
;
1176 InitializeFormatDriveDlg(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
1177 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
1180 switch(LOWORD(wParam
))
1183 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1184 FormatDrive(hwndDlg
, pContext
);
1187 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1188 EndDialog(hwndDlg
, pContext
->Result
);
1190 case 28677: // filesystem combo
1191 if (HIWORD(wParam
) == CBN_SELENDOK
)
1193 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1194 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
1204 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
)
1206 INITIALIZE_FMIFS InitFmifs
;
1210 hLibrary
= pContext
->hLibrary
= LoadLibraryW(L
"fmifs.dll");
1213 ERR("failed to load fmifs.dll\n");
1217 InitFmifs
= (INITIALIZE_FMIFS
)GetProcAddress(hLibrary
, "InitializeFmIfs");
1220 ERR("InitializeFmIfs export is missing\n");
1221 FreeLibrary(hLibrary
);
1225 ret
= (*InitFmifs
)(NULL
, DLL_PROCESS_ATTACH
, NULL
);
1228 ERR("fmifs failed to initialize\n");
1229 FreeLibrary(hLibrary
);
1233 pContext
->QueryAvailableFileSystemFormat
= (QUERY_AVAILABLEFSFORMAT
)GetProcAddress(hLibrary
, "QueryAvailableFileSystemFormat");
1234 if (!pContext
->QueryAvailableFileSystemFormat
)
1236 ERR("QueryAvailableFileSystemFormat export is missing\n");
1237 FreeLibrary(hLibrary
);
1241 pContext
->FormatEx
= (FORMAT_EX
) GetProcAddress(hLibrary
, "FormatEx");
1242 if (!pContext
->FormatEx
)
1244 ERR("FormatEx export is missing\n");
1245 FreeLibrary(hLibrary
);
1249 pContext
->EnableVolumeCompression
= (ENABLEVOLUMECOMPRESSION
) GetProcAddress(hLibrary
, "EnableVolumeCompression");
1250 if (!pContext
->FormatEx
)
1252 ERR("EnableVolumeCompression export is missing\n");
1253 FreeLibrary(hLibrary
);
1257 pContext
->Chkdsk
= (CHKDSK
) GetProcAddress(hLibrary
, "Chkdsk");
1258 if (!pContext
->Chkdsk
)
1260 ERR("Chkdsk export is missing\n");
1261 FreeLibrary(hLibrary
);
1268 /*************************************************************************
1269 * SHFormatDrive (SHELL32.@)
1274 SHFormatDrive(HWND hwnd
, UINT drive
, UINT fmtID
, UINT options
)
1276 FORMAT_DRIVE_CONTEXT Context
;
1279 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd
, drive
, fmtID
, options
);
1281 if (!InitializeFmifsLibrary(&Context
))
1283 ERR("failed to initialize fmifs\n");
1284 return SHFMT_NOFORMAT
;
1287 Context
.Drive
= drive
;
1288 Context
.Options
= options
;
1290 result
= DialogBoxParamW(shell32_hInstance
, L
"FORMAT_DLG", hwnd
, FormatDriveDlg
, (LPARAM
)&Context
);
1292 FreeLibrary(Context
.hLibrary
);