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
101 QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat
;
103 ENABLEVOLUMECOMPRESSION EnableVolumeCompression
;
105 }FORMAT_DRIVE_CONTEXT
, *PFORMAT_DRIVE_CONTEXT
;
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 extern HINSTANCE shell32_hInstance
;
121 GetFreeBytesShare(LARGE_INTEGER TotalNumberOfFreeBytes
, LARGE_INTEGER TotalNumberOfBytes
)
123 LARGE_INTEGER Temp
, Result
, Remainder
;
125 Temp
= LargeIntegerDivide(TotalNumberOfBytes
, ConvertUlongToLargeInteger(100), &Remainder
);
126 if (Temp
.QuadPart
>= TotalNumberOfFreeBytes
.QuadPart
)
128 Result
= ConvertUlongToLargeInteger(1);
131 Result
= LargeIntegerDivide(TotalNumberOfFreeBytes
, Temp
, &Remainder
);
139 PaintStaticControls(HWND hwndDlg
, LPDRAWITEMSTRUCT drawItem
)
143 if (drawItem
->CtlID
== 14013)
145 hBrush
= CreateSolidBrush(RGB(0, 0, 255));
148 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
149 DeleteObject((HGDIOBJ
)hBrush
);
151 }else if (drawItem
->CtlID
== 14014)
153 hBrush
= CreateSolidBrush(RGB(255, 0, 255));
156 FillRect(drawItem
->hDC
, &drawItem
->rcItem
, hBrush
);
157 DeleteObject((HGDIOBJ
)hBrush
);
160 else if (drawItem
->CtlID
== 14015)
166 LARGE_INTEGER Result
;
169 hBlueBrush
= CreateSolidBrush(RGB(0, 0, 255));
170 hMagBrush
= CreateSolidBrush(RGB(255, 0, 255));
172 SendDlgItemMessageW(hwndDlg
, 14007, WM_GETTEXT
, 20, (LPARAM
)szBuffer
);
173 Result
.QuadPart
= _wtoi(szBuffer
);
175 CopyRect(&rect
, &drawItem
->rcItem
);
176 horzsize
= rect
.right
- rect
.left
;
177 Result
.QuadPart
= (Result
.QuadPart
* horzsize
) / 100;
179 rect
.right
= rect
.left
+ Result
.QuadPart
;
180 FillRect(drawItem
->hDC
, &rect
, hMagBrush
);
181 rect
.left
= rect
.right
;
182 rect
.right
= drawItem
->rcItem
.right
;
183 FillRect(drawItem
->hDC
, &rect
, hBlueBrush
);
184 DeleteObject(hBlueBrush
);
185 DeleteObject(hMagBrush
);
191 InitializeGeneralDriveDialog(HWND hwndDlg
, WCHAR
* szDrive
)
193 WCHAR szVolumeName
[MAX_PATH
+1] = {0};
194 DWORD MaxComponentLength
= 0;
195 DWORD FileSystemFlags
= 0;
196 WCHAR FileSystemName
[MAX_PATH
+1] = {0};
201 ULARGE_INTEGER FreeBytesAvailable
;
202 LARGE_INTEGER TotalNumberOfFreeBytes
;
203 LARGE_INTEGER TotalNumberOfBytes
;
205 ret
= GetVolumeInformationW(szDrive
, szVolumeName
, MAX_PATH
+1, NULL
, &MaxComponentLength
, &FileSystemFlags
, FileSystemName
, MAX_PATH
+1);
208 /* set volume label */
209 SendDlgItemMessageW(hwndDlg
, 14001, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szVolumeName
);
211 /* set filesystem type */
212 SendDlgItemMessageW(hwndDlg
, 14003, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)FileSystemName
);
216 DriveType
= GetDriveTypeW(szDrive
);
217 if (DriveType
== DRIVE_FIXED
)
220 if(GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailable
, (PULARGE_INTEGER
)&TotalNumberOfBytes
, (PULARGE_INTEGER
)&TotalNumberOfFreeBytes
))
223 LARGE_INTEGER Result
;
224 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
226 DWORD BytesReturned
= 0;
228 sprintfW(szResult
, L
"\\\\.\\%c:", towupper(szDrive
[0]));
229 hVolume
= CreateFileW(szResult
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
230 if (hVolume
!= INVALID_HANDLE_VALUE
)
232 ret
= DeviceIoControl(hVolume
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, (LPVOID
)&TotalNumberOfBytes
, sizeof(ULARGE_INTEGER
), &BytesReturned
, NULL
);
233 if (ret
&& StrFormatByteSizeW(LengthInformation
.Length
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
234 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
236 CloseHandle(hVolume
);
238 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult
), hVolume
, ret
, LengthInformation
.Length
.QuadPart
, BytesReturned
);
240 if (ret
&& StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
241 SendDlgItemMessageW(hwndDlg
, 14008, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
244 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
- FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
245 SendDlgItemMessageW(hwndDlg
, 14004, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
247 if (StrFormatByteSizeW(FreeBytesAvailable
.QuadPart
, szResult
, sizeof(szResult
) / sizeof(WCHAR
)))
248 SendDlgItemMessageW(hwndDlg
, 14006, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szResult
);
250 Result
= GetFreeBytesShare(TotalNumberOfFreeBytes
, TotalNumberOfBytes
);
251 /* set free bytes percentage */
252 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
253 SendDlgItemMessageW(hwndDlg
, 14007, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
254 /* store used share amount */
255 Result
= LargeIntegerSubtract(ConvertUlongToLargeInteger(100), Result
);
256 swprintf(szResult
, L
"%02d%%", Result
.QuadPart
);
257 SendDlgItemMessageW(hwndDlg
, 14005, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szResult
);
258 if (LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szBuffer
, sizeof(szBuffer
) / sizeof(WCHAR
)))
259 SendDlgItemMessageW(hwndDlg
, 14002, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szBuffer
);
263 /* set drive description */
264 SendDlgItemMessageW(hwndDlg
, 14010, WM_GETTEXT
, (WPARAM
)50, (LPARAM
)szFormat
);
265 swprintf(szBuffer
, szFormat
, szDrive
);
266 SendDlgItemMessageW(hwndDlg
, 14010, WM_SETTEXT
, (WPARAM
)NULL
, (LPARAM
)szBuffer
);
279 LPPROPSHEETPAGEW ppsp
;
280 LPDRAWITEMSTRUCT drawItem
;
282 PROCESS_INFORMATION pi
;
284 WCHAR szPath
[MAX_PATH
];
291 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
294 lpstr
= (WCHAR
*)ppsp
->lParam
;
295 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lpstr
);
296 InitializeGeneralDriveDialog(hwndDlg
, lpstr
);
299 drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
300 if (drawItem
->CtlID
>= 14013 && drawItem
->CtlID
<= 14015)
302 PaintStaticControls(hwndDlg
, drawItem
);
307 if (LOWORD(wParam
) == 14011)
309 lpstr
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
310 ZeroMemory( &si
, sizeof(si
) );
312 ZeroMemory( &pi
, sizeof(pi
) );
313 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
315 wcscat(szPath
, L
"\\cleanmgr.exe /D ");
316 length
= wcslen(szPath
);
317 szPath
[length
] = lpstr
[0];
318 szPath
[length
+1] = L
'\0';
319 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
321 CloseHandle(pi
.hProcess
);
322 CloseHandle(pi
.hThread
);
327 lppsn
= (LPPSHNOTIFY
) lParam
;
328 if (LOWORD(wParam
) == 14001)
330 if (HIWORD(wParam
) == EN_CHANGE
)
332 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
336 if (lppsn
->hdr
.code
== PSN_APPLY
)
338 lpstr
= (LPWSTR
)GetWindowLong(hwndDlg
, DWLP_USER
);
339 if (lpstr
&& SendDlgItemMessageW(hwndDlg
, 14001, WM_GETTEXT
, sizeof(szPath
)/sizeof(WCHAR
), (LPARAM
)szPath
))
341 szPath
[(sizeof(szPath
)/sizeof(WCHAR
))-1] = L
'\0';
342 SetVolumeLabelW(lpstr
, szPath
);
344 SetWindowLong( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
367 PROCESS_INFORMATION pi
;
368 WCHAR szPath
[MAX_PATH
];
369 WCHAR szArg
[MAX_PATH
];
372 LPPROPSHEETPAGEW ppsp
;
377 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
378 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)ppsp
->lParam
);
381 ZeroMemory( &si
, sizeof(si
) );
383 ZeroMemory( &pi
, sizeof(pi
) );
384 if (!GetSystemDirectoryW(szPath
, MAX_PATH
))
386 szDrive
= (WCHAR
*)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
387 switch(LOWORD(wParam
))
392 /// show checkdsk dialog
397 wcscpy(&szArg
[1], szPath
);
398 wcscat(szPath
, L
"\\mmc.exe");
399 wcscat(szArg
, L
"\\dfrg.msc\" ");
400 length
= wcslen(szArg
);
401 szArg
[length
] = szDrive
[0];
402 szArg
[length
+1] = L
':';
403 szArg
[length
+2] = L
'\0';
404 if (CreateProcessW(szPath
, szArg
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
406 CloseHandle(pi
.hProcess
);
407 CloseHandle(pi
.hThread
);
411 wcscat(szPath
, L
"\\ntbackup.exe");
412 if (CreateProcessW(szPath
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
414 CloseHandle(pi
.hProcess
);
415 CloseHandle(pi
.hThread
);
433 Guids
[0] = GUID_DEVCLASS_DISKDRIVE
;
435 UNREFERENCED_PARAMETER(lParam
);
436 UNREFERENCED_PARAMETER(wParam
);
441 /* create the hardware page */
442 DeviceCreateHardwarePageEx(hwndDlg
,
444 sizeof(Guids
) / sizeof(Guids
[0]),
460 { "DRIVE_GENERAL_DLG", DriveGeneralDlg
},
461 { "DRIVE_EXTRA_DLG", DriveExtraDlg
},
462 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg
},
467 AddPropSheetPageProc(HPROPSHEETPAGE hpage
, LPARAM lParam
)
469 PROPSHEETHEADER
*ppsh
= (PROPSHEETHEADER
*)lParam
;
470 if (ppsh
!= NULL
&& ppsh
->nPages
< MAX_PROPERTY_SHEET_PAGE
)
472 ppsh
->phpage
[ppsh
->nPages
++] = hpage
;
479 SH_ShowDriveProperties(WCHAR
* drive
)
482 HPROPSHEETPAGE hpsp
[MAX_PROPERTY_SHEET_PAGE
];
483 PROPSHEETHEADERW psh
;
486 WCHAR szName
[MAX_PATH
];
487 DWORD dwMaxComponent
, dwFileSysFlags
;
489 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
490 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
491 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
492 psh
.hwndParent
= NULL
;
497 if (GetVolumeInformationW(drive
, szName
, sizeof(szName
)/sizeof(WCHAR
), NULL
, &dwMaxComponent
,
498 &dwFileSysFlags
, NULL
, 0))
500 psh
.pszCaption
= szName
;
501 psh
.dwFlags
|= PSH_PROPTITLE
;
505 * check if disk is a really a local hdd
507 i
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, szName
, sizeof(szName
)/sizeof(WCHAR
));
508 if (i
> 0 && i
< (sizeof(szName
)/sizeof(WCHAR
)) + 6)
512 wcscpy(&szName
[i
+2], drive
);
520 for (i
= 0; i
< DRIVE_PROPERTY_PAGES
; i
++)
522 HPROPSHEETPAGE hprop
= SH_CreatePropertySheetPage(PropPages
[i
].resname
, PropPages
[i
].dlgproc
, (LPARAM
)drive
, NULL
);
525 hpsp
[psh
.nPages
] = hprop
;
530 hpsx
= SHCreatePropSheetExtArray(HKEY_CLASSES_ROOT
,
532 MAX_PROPERTY_SHEET_PAGE
-DRIVE_PROPERTY_PAGES
);
534 SHAddFromPropSheetExtArray(hpsx
,
535 (LPFNADDPROPSHEETPAGE
)AddPropSheetPageProc
,
538 ret
= PropertySheetW(&psh
);
550 InsertDefaultClusterSizeForFs(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
552 WCHAR szFs
[100] = {0};
553 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
555 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
560 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
561 iSelIndex
= SendMessage(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
562 if (iSelIndex
== CB_ERR
)
565 if (SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFs
) == CB_ERR
)
568 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
569 szDrive
[0] = pContext
->Drive
+ 'A';
571 if (!GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
574 if (!wcsicmp(szFs
, L
"FAT16") ||
575 !wcsicmp(szFs
, L
"FAT")) //REACTOS HACK
577 if (TotalNumberOfBytes
.QuadPart
<= (16 * 1024 * 1024))
579 else if (TotalNumberOfBytes
.QuadPart
<= (32 * 1024 * 1024))
581 else if (TotalNumberOfBytes
.QuadPart
<= (64 * 1024 * 1024))
583 else if (TotalNumberOfBytes
.QuadPart
<= (128 * 1024 * 1024))
585 else if (TotalNumberOfBytes
.QuadPart
<= (256 * 1024 * 1024))
587 else if (TotalNumberOfBytes
.QuadPart
<= (512 * 1024 * 1024))
589 else if (TotalNumberOfBytes
.QuadPart
<= (1024 * 1024 * 1024))
591 else if (TotalNumberOfBytes
.QuadPart
<= (2048LL * 1024LL * 1024LL))
593 else if (TotalNumberOfBytes
.QuadPart
<= (4096LL * 1024LL * 1024LL))
597 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes
.QuadPart
);
598 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
601 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
603 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
604 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
605 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
606 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
607 if (lIndex
!= CB_ERR
)
608 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
609 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
612 else if (!wcsicmp(szFs
, L
"FAT32"))
614 if (TotalNumberOfBytes
.QuadPart
<=(64 * 1024 * 1024))
616 else if (TotalNumberOfBytes
.QuadPart
<= (128 * 1024 * 1024))
618 else if (TotalNumberOfBytes
.QuadPart
<= (256 * 1024 * 1024))
620 else if (TotalNumberOfBytes
.QuadPart
<= (8192LL * 1024LL * 1024LL))
622 else if (TotalNumberOfBytes
.QuadPart
<= (16384LL * 1024LL * 1024LL))
624 else if (TotalNumberOfBytes
.QuadPart
<= (32768LL * 1024LL * 1024LL))
628 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes
.QuadPart
);
629 SendMessageW(hDlgCtrl
, CB_DELETESTRING
, iSelIndex
, 0);
633 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
635 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
636 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
637 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
638 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
639 if (lIndex
!= CB_ERR
)
640 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
641 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
644 else if (!wcsicmp(szFs
, L
"NTFS"))
646 if (TotalNumberOfBytes
.QuadPart
<=(512 * 1024 * 1024))
648 else if (TotalNumberOfBytes
.QuadPart
<= (1024 * 1024 * 1024))
650 else if (TotalNumberOfBytes
.QuadPart
<= (2048LL * 1024LL * 1024LL))
655 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
656 if (LoadStringW(shell32_hInstance
, IDS_DEFAULT_CLUSTER_SIZE
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
658 szFs
[(sizeof(szFs
)/sizeof(WCHAR
))-1] = L
'\0';
659 SendMessageW(hDlgCtrl
, CB_RESETCONTENT
, 0, 0);
660 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
661 if (lIndex
!= CB_ERR
)
662 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
663 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, 0, 0);
666 for (lIndex
= 0; lIndex
< 4; lIndex
++)
668 TotalNumberOfBytes
.QuadPart
= ClusterSize
;
669 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
671 lIndex
= SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szFs
);
672 if (lIndex
!= CB_ERR
)
673 SendMessageW(hDlgCtrl
, CB_SETITEMDATA
, lIndex
, (LPARAM
)ClusterSize
);
680 FIXME("unknown fs\n");
681 SendDlgItemMessageW(hwndDlg
, 28680, CB_RESETCONTENT
, iSelIndex
, 0);
687 InitializeFormatDriveDlg(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
690 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
691 WCHAR szFs
[30] = {0};
692 INT Length
, TempLength
;
693 DWORD dwSerial
, dwMaxComp
, dwFileSys
;
694 ULARGE_INTEGER FreeBytesAvailableUser
, TotalNumberOfBytes
;
695 DWORD dwIndex
, dwDefault
;
696 UCHAR uMinor
, uMajor
;
700 Length
= GetWindowTextW(hwndDlg
, szText
, sizeof(szText
)/sizeof(WCHAR
));
701 szDrive
[0] = pContext
->Drive
+ L
'A';
702 if (GetVolumeInformationW(szDrive
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2, &dwSerial
, &dwMaxComp
, &dwFileSys
, szFs
, sizeof(szFs
)/sizeof(WCHAR
)))
704 szText
[Length
] = L
' ';
705 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
706 TempLength
= wcslen(&szText
[Length
+1]);
709 /* load default volume label */
710 TempLength
= LoadStringW(shell32_hInstance
, IDS_DRIVE_FIXED
, &szText
[Length
+1], (sizeof(szText
)/sizeof(WCHAR
))- Length
- 2);
714 /* set volume label */
715 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
716 SendDlgItemMessageW(hwndDlg
, 28679, WM_SETTEXT
, 0, (LPARAM
)&szText
[Length
+1]);
718 Length
+= TempLength
+ 1;
721 if (Length
+ 4 < (sizeof(szText
)/sizeof(WCHAR
)))
723 szText
[Length
] = L
' ';
724 szText
[Length
+1] = L
'(';
725 szText
[Length
+2] = szDrive
[0];
726 szText
[Length
+3] = L
')';
730 if (Length
< (sizeof(szText
)/sizeof(WCHAR
)))
731 szText
[Length
] = L
'\0';
733 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
735 /* set window text */
736 SetWindowTextW(hwndDlg
, szText
);
738 if (GetDiskFreeSpaceExW(szDrive
, &FreeBytesAvailableUser
, &TotalNumberOfBytes
, NULL
))
740 if (StrFormatByteSizeW(TotalNumberOfBytes
.QuadPart
, szText
, sizeof(szText
)/sizeof(WCHAR
)))
742 /* add drive capacity */
743 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
744 SendDlgItemMessageW(hwndDlg
, 28673, CB_ADDSTRING
, 0, (LPARAM
)szText
);
745 SendDlgItemMessageW(hwndDlg
, 28673, CB_SETCURSEL
, 0, (LPARAM
)0);
749 if (pContext
->Options
& SHFMT_OPT_FULL
)
751 /* check quick format button */
752 SendDlgItemMessageW(hwndDlg
, 28674, BM_SETCHECK
, BST_CHECKED
, 0);
755 /* enumerate all available filesystems */
758 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
760 while(pContext
->QueryAvailableFileSystemFormat(dwIndex
, szText
, &uMajor
, &uMinor
, &Latest
))
762 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = L
'\0';
763 if (!wcsicmp(szText
, szFs
))
766 SendMessageW(hDlgCtrl
, CB_ADDSTRING
, 0, (LPARAM
)szText
);
772 ERR("no filesystem providers\n");
776 /* select default filesys */
777 SendMessageW(hDlgCtrl
, CB_SETCURSEL
, dwDefault
, 0);
778 /* setup cluster combo */
779 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
780 /* hide progress control */
781 ShowWindow(GetDlgItem(hwndDlg
, 28678), SW_HIDE
);
784 HWND FormatDrvDialog
= NULL
;
785 BOOLEAN bSuccess
= FALSE
;
791 IN CALLBACKCOMMAND Command
,
800 Progress
= (PDWORD
)ActionInfo
;
801 SendDlgItemMessageW(FormatDrvDialog
, 28678, PBM_SETPOS
, (WPARAM
)*Progress
, 0);
804 pSuccess
= (PBOOLEAN
)ActionInfo
;
805 bSuccess
= (*pSuccess
);
809 case INSUFFICIENTRIGHTS
:
811 case CLUSTERSIZETOOSMALL
:
828 FormatDrive(HWND hwndDlg
, PFORMAT_DRIVE_CONTEXT pContext
)
830 WCHAR szDrive
[4] = { L
'C', ':', '\\', 0 };
831 WCHAR szFileSys
[40] = {0};
832 WCHAR szLabel
[40] = {0};
839 /* set volume path */
840 szDrive
[0] = pContext
->Drive
;
843 hDlgCtrl
= GetDlgItem(hwndDlg
, 28677);
844 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
845 if (iSelIndex
== CB_ERR
)
850 Length
= SendMessageW(hDlgCtrl
, CB_GETLBTEXTLEN
, iSelIndex
, 0);
851 if (Length
== CB_ERR
|| Length
+ 1> sizeof(szFileSys
)/sizeof(WCHAR
))
857 /* retrieve the file system */
858 SendMessageW(hDlgCtrl
, CB_GETLBTEXT
, iSelIndex
, (LPARAM
)szFileSys
);
859 szFileSys
[(sizeof(szFileSys
)/sizeof(WCHAR
))-1] = L
'\0';
861 /* retrieve the volume label */
862 hDlgCtrl
= GetWindow(hwndDlg
, 28679);
863 Length
= SendMessageW(hDlgCtrl
, WM_GETTEXTLENGTH
, 0, 0);
864 if (Length
+ 1 > sizeof(szLabel
)/sizeof(WCHAR
))
869 SendMessageW(hDlgCtrl
, WM_GETTEXT
, sizeof(szLabel
)/sizeof(WCHAR
), (LPARAM
)szLabel
);
870 szLabel
[(sizeof(szLabel
)/sizeof(WCHAR
))-1] = L
'\0';
872 /* check for quickformat */
873 if (SendDlgItemMessageW(hwndDlg
, 28674, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
878 /* get the cluster size */
879 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
880 iSelIndex
= SendMessageW(hDlgCtrl
, CB_GETCURSEL
, 0, 0);
881 if (iSelIndex
== CB_ERR
)
886 ClusterSize
= SendMessageW(hDlgCtrl
, CB_GETITEMDATA
, iSelIndex
, 0);
887 if (ClusterSize
== CB_ERR
)
893 hDlgCtrl
= GetDlgItem(hwndDlg
, 28680);
894 ShowWindow(hDlgCtrl
, SW_SHOW
);
895 SendMessageW(hDlgCtrl
, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
899 * will cause display problems
900 * when performing more than one format
902 FormatDrvDialog
= hwndDlg
;
904 pContext
->FormatEx(szDrive
,
905 FMIFS_HARDDISK
, /* FIXME */
912 ShowWindow(hDlgCtrl
, SW_HIDE
);
913 FormatDrvDialog
= NULL
;
916 pContext
->Result
= SHFMT_ERROR
;
918 else if (QuickFormat
)
920 pContext
->Result
= SHFMT_OPT_FULL
;
924 pContext
->Result
= FALSE
;
931 FormatDriveDlg(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
933 PFORMAT_DRIVE_CONTEXT pContext
;
938 InitializeFormatDriveDlg(hwndDlg
, (PFORMAT_DRIVE_CONTEXT
)lParam
);
939 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)lParam
);
942 switch(LOWORD(wParam
))
945 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
946 FormatDrive(hwndDlg
, pContext
);
949 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
950 EndDialog(hwndDlg
, pContext
->Result
);
952 case 28677: // filesystem combo
953 if (HIWORD(wParam
) == CBN_SELENDOK
)
955 pContext
= (PFORMAT_DRIVE_CONTEXT
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
956 InsertDefaultClusterSizeForFs(hwndDlg
, pContext
);
966 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext
)
968 INITIALIZE_FMIFS InitFmifs
;
972 hLibrary
= pContext
->hLibrary
= LoadLibraryW(L
"fmifs.dll");
975 ERR("failed to load fmifs.dll\n");
979 InitFmifs
= (INITIALIZE_FMIFS
)GetProcAddress(hLibrary
, "InitializeFmIfs");
982 ERR("InitializeFmIfs export is missing\n");
983 FreeLibrary(hLibrary
);
987 ret
= (*InitFmifs
)(NULL
, DLL_PROCESS_ATTACH
, NULL
);
990 ERR("fmifs failed to initialize\n");
991 FreeLibrary(hLibrary
);
995 pContext
->QueryAvailableFileSystemFormat
= (QUERY_AVAILABLEFSFORMAT
)GetProcAddress(hLibrary
, "QueryAvailableFileSystemFormat");
996 if (!pContext
->QueryAvailableFileSystemFormat
)
998 ERR("QueryAvailableFileSystemFormat export is missing\n");
999 FreeLibrary(hLibrary
);
1003 pContext
->FormatEx
= (FORMAT_EX
) GetProcAddress(hLibrary
, "FormatEx");
1004 if (!pContext
->FormatEx
)
1006 ERR("FormatEx export is missing\n");
1007 FreeLibrary(hLibrary
);
1011 pContext
->EnableVolumeCompression
= (ENABLEVOLUMECOMPRESSION
) GetProcAddress(hLibrary
, "EnableVolumeCompression");
1012 if (!pContext
->FormatEx
)
1014 ERR("EnableVolumeCompression export is missing\n");
1015 FreeLibrary(hLibrary
);
1022 /*************************************************************************
1023 * SHFormatDrive (SHELL32.@)
1028 SHFormatDrive(HWND hwnd
, UINT drive
, UINT fmtID
, UINT options
)
1030 FORMAT_DRIVE_CONTEXT Context
;
1033 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd
, drive
, fmtID
, options
);
1035 if (!InitializeFmifsLibrary(&Context
))
1037 ERR("failed to initialize fmifs\n");
1038 return SHFMT_NOFORMAT
;
1041 Context
.Drive
= drive
;
1042 Context
.Options
= options
;
1044 result
= DialogBoxParamW(shell32_hInstance
, L
"FORMAT_DLG", hwnd
, FormatDriveDlg
, (LPARAM
)&Context
);
1046 FreeLibrary(Context
.hLibrary
);