[HAL]
[reactos.git] / reactos / dll / win32 / shell32 / drive.c
1 /*
2 * Shell Library Functions
3 *
4 * Copyright 2005 Johannes Anderwald
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define MAX_PROPERTY_SHEET_PAGE 32
22
23 #define WIN32_NO_STATUS
24 #define NTOS_MODE_USER
25 #define UNICODE
26 #define _UNICODE
27 #define COBJMACROS
28 #include <windows.h>
29 #include <ndk/ntndk.h>
30 #include <fmifs/fmifs.h>
31 #include <largeint.h>
32
33 #include <precomp.h>
34
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
36
37 typedef enum
38 {
39 HWPD_STANDARDLIST = 0,
40 HWPD_LARGELIST,
41 HWPD_MAX = HWPD_LARGELIST
42 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
43
44 typedef
45 BOOLEAN
46 (NTAPI *INITIALIZE_FMIFS)(
47 IN PVOID hinstDll,
48 IN DWORD dwReason,
49 IN PVOID reserved
50 );
51 typedef
52 BOOLEAN
53 (NTAPI *QUERY_AVAILABLEFSFORMAT)(
54 IN DWORD Index,
55 IN OUT PWCHAR FileSystem,
56 OUT UCHAR* Major,
57 OUT UCHAR* Minor,
58 OUT BOOLEAN* LastestVersion
59 );
60 typedef
61 BOOLEAN
62 (NTAPI *ENABLEVOLUMECOMPRESSION)(
63 IN PWCHAR DriveRoot,
64 IN USHORT Compression
65 );
66
67 typedef
68 VOID
69 (NTAPI *FORMAT_EX)(
70 IN PWCHAR DriveRoot,
71 IN FMIFS_MEDIA_FLAG MediaFlag,
72 IN PWCHAR Format,
73 IN PWCHAR Label,
74 IN BOOLEAN QuickFormat,
75 IN ULONG ClusterSize,
76 IN PFMIFSCALLBACK Callback
77 );
78
79 typedef
80 VOID
81 (NTAPI *CHKDSK)(
82 IN PWCHAR DriveRoot,
83 IN PWCHAR Format,
84 IN BOOLEAN CorrectErrors,
85 IN BOOLEAN Verbose,
86 IN BOOLEAN CheckOnlyIfDirty,
87 IN BOOLEAN ScanDrive,
88 IN PVOID Unused2,
89 IN PVOID Unused3,
90 IN PFMIFSCALLBACK Callback
91 );
92
93
94 typedef struct
95 {
96 WCHAR Drive;
97 UINT Options;
98 HMODULE hLibrary;
99 QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat;
100 FORMAT_EX FormatEx;
101 ENABLEVOLUMECOMPRESSION EnableVolumeCompression;
102 CHKDSK Chkdsk;
103 UINT Result;
104 }FORMAT_DRIVE_CONTEXT, *PFORMAT_DRIVE_CONTEXT;
105
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);
109 HWND WINAPI
110 DeviceCreateHardwarePageEx(HWND hWndParent,
111 LPGUID lpGuids,
112 UINT uNumberOfGuids,
113 HWPAGE_DISPLAYMODE DisplayMode);
114
115 HPROPSHEETPAGE SH_CreatePropertySheetPage(LPSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle);
116
117 #define DRIVE_PROPERTY_PAGES (3)
118
119 static const GUID GUID_DEVCLASS_DISKDRIVE = {0x4d36e967L, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
120
121
122 VOID
123 GetDriveNameWithLetter(LPWSTR szText, UINT Length, WCHAR Drive)
124 {
125 WCHAR szDrive[] = {'C',':','\\', 0};
126 DWORD dwMaxComp, dwFileSys, TempLength = 0;
127
128 szDrive[0] = Drive;
129 if (GetVolumeInformationW(szDrive, szText, Length, NULL, &dwMaxComp, &dwFileSys, NULL, 0))
130 {
131 szText[Length-1] = L'\0';
132 TempLength = wcslen(szText);
133 if (!TempLength)
134 {
135 /* load default volume label */
136 TempLength = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2);
137 }
138 }
139 if (TempLength + 4 < Length)
140 {
141 szText[TempLength] = L' ';
142 szText[TempLength+1] = L'(';
143 szText[TempLength+2] = szDrive[0];
144 szText[TempLength+3] = L')';
145 TempLength +=4;
146 }
147
148 if (TempLength < Length)
149 szText[TempLength] = L'\0';
150 else
151 szText[Length-1] = L'\0';
152 }
153
154
155 VOID
156 InitializeChkDskDialog(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
157 {
158 WCHAR szText[100];
159 UINT Length;
160 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pContext);
161
162 Length = GetWindowTextW(hwndDlg, szText, sizeof(szText)/sizeof(WCHAR));
163
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);
168 }
169
170 HWND ChkdskDrvDialog = NULL;
171 BOOLEAN bChkdskSuccess = FALSE;
172
173 BOOLEAN
174 NTAPI
175 ChkdskCallback(
176 IN CALLBACKCOMMAND Command,
177 IN ULONG SubAction,
178 IN PVOID ActionInfo)
179 {
180 PDWORD Progress;
181 PBOOLEAN pSuccess;
182 switch(Command)
183 {
184 case PROGRESS:
185 Progress = (PDWORD)ActionInfo;
186 SendDlgItemMessageW(ChkdskDrvDialog, 14002, PBM_SETPOS, (WPARAM)*Progress, 0);
187 break;
188 case DONE:
189 pSuccess = (PBOOLEAN)ActionInfo;
190 bChkdskSuccess = (*pSuccess);
191 break;
192
193 case VOLUMEINUSE:
194 case INSUFFICIENTRIGHTS:
195 case FSNOTSUPPORTED:
196 case CLUSTERSIZETOOSMALL:
197 bChkdskSuccess = FALSE;
198 FIXME("\n");
199 break;
200
201 default:
202 break;
203 }
204
205 return TRUE;
206 }
207
208 VOID
209 ChkDskNow(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
210 {
211 DWORD ClusterSize = 0, dwMaxComponentLength, FileSystemFlags;
212 WCHAR szFs[30];
213 WCHAR szDrive[] = {'C',':','\\', 0};
214 WCHAR szVolumeLabel[40];
215 ULARGE_INTEGER TotalNumberOfFreeBytes, FreeBytesAvailableUser;
216 BOOLEAN bCorrectErrors = FALSE, bScanDrive = FALSE;
217
218 szDrive[0] = pContext->Drive;
219 if(!GetVolumeInformationW(szDrive, szVolumeLabel, sizeof(szVolumeLabel)/sizeof(WCHAR), NULL, &dwMaxComponentLength, &FileSystemFlags, szFs, sizeof(szFs)/sizeof(WCHAR)))
220 {
221 FIXME("failed to get drive fs type\n");
222 return;
223 }
224
225 if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfFreeBytes, NULL))
226 {
227 FIXME("failed to get drive space type\n");
228 return;
229 }
230
231 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfFreeBytes))
232 {
233 FIXME("invalid cluster size\n");
234 return;
235 }
236
237 if (SendDlgItemMessageW(hwndDlg, 14000, BM_GETCHECK, 0, 0) == BST_CHECKED)
238 bCorrectErrors = TRUE;
239
240 if (SendDlgItemMessageW(hwndDlg, 14001, BM_GETCHECK, 0, 0) == BST_CHECKED)
241 bScanDrive = TRUE;
242
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);
247
248 ChkdskDrvDialog = NULL;
249 pContext->Result = bChkdskSuccess;
250 bChkdskSuccess = FALSE;
251
252 }
253
254 INT_PTR
255 CALLBACK
256 ChkDskDlg(
257 HWND hwndDlg,
258 UINT uMsg,
259 WPARAM wParam,
260 LPARAM lParam
261 )
262 {
263 PFORMAT_DRIVE_CONTEXT pContext;
264 switch(uMsg)
265 {
266 case WM_INITDIALOG:
267 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
268 InitializeChkDskDialog(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
269 return TRUE;
270 case WM_COMMAND:
271 switch(LOWORD(wParam))
272 {
273 case IDCANCEL:
274 EndDialog(hwndDlg, 0);
275 break;
276 case IDOK:
277 pContext = (PFORMAT_DRIVE_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);
278 ChkDskNow(hwndDlg, pContext);
279 break;
280 }
281 break;
282 }
283
284 return FALSE;
285 }
286
287
288 static
289 ULONGLONG
290 GetFreeBytesShare(ULONGLONG TotalNumberOfFreeBytes, ULONGLONG TotalNumberOfBytes)
291 {
292 ULONGLONG Temp;
293
294 if (TotalNumberOfFreeBytes == 0LL)
295 {
296 return 0;
297 }
298
299 Temp = TotalNumberOfBytes / 100;
300 if (Temp >= TotalNumberOfFreeBytes)
301 {
302 return 1;
303 }
304 else
305 {
306 return TotalNumberOfFreeBytes / Temp;
307 }
308 }
309
310 static
311 void
312 PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT drawItem)
313 {
314 HBRUSH hBrush;
315
316 if (drawItem->CtlID == 14013)
317 {
318 hBrush = CreateSolidBrush(RGB(0, 0, 255));
319 if (hBrush)
320 {
321 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
322 DeleteObject((HGDIOBJ)hBrush);
323 }
324 }
325 else if (drawItem->CtlID == 14014)
326 {
327 hBrush = CreateSolidBrush(RGB(255, 0, 255));
328 if (hBrush)
329 {
330 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
331 DeleteObject((HGDIOBJ)hBrush);
332 }
333 }
334 else if (drawItem->CtlID == 14015)
335 {
336 HBRUSH hBlueBrush;
337 HBRUSH hMagBrush;
338 RECT rect;
339 LONG horzsize;
340 LONGLONG Result;
341 WCHAR szBuffer[20];
342
343 hBlueBrush = CreateSolidBrush(RGB(0, 0, 255));
344 hMagBrush = CreateSolidBrush(RGB(255, 0, 255));
345
346 SendDlgItemMessageW(hwndDlg, 14006, WM_GETTEXT, 20, (LPARAM)szBuffer);
347 Result = _wtoi(szBuffer);
348
349 CopyRect(&rect, &drawItem->rcItem);
350 horzsize = rect.right - rect.left;
351 Result = (Result * horzsize) / 100;
352
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);
360 }
361 }
362
363 static
364 void
365 InitializeGeneralDriveDialog(HWND hwndDlg, WCHAR * szDrive)
366 {
367 WCHAR szVolumeName[MAX_PATH+1] = {0};
368 DWORD MaxComponentLength = 0;
369 DWORD FileSystemFlags = 0;
370 WCHAR FileSystemName[MAX_PATH+1] = {0};
371 WCHAR szFormat[50];
372 WCHAR szBuffer[128];
373 BOOL ret;
374 UINT DriveType;
375 ULARGE_INTEGER FreeBytesAvailable;
376 LARGE_INTEGER TotalNumberOfFreeBytes;
377 LARGE_INTEGER TotalNumberOfBytes;
378
379 ret = GetVolumeInformationW(szDrive, szVolumeName, MAX_PATH+1, NULL, &MaxComponentLength, &FileSystemFlags, FileSystemName, MAX_PATH+1);
380 if (ret)
381 {
382 /* set volume label */
383 SendDlgItemMessageW(hwndDlg, 14000, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szVolumeName);
384
385 /* set filesystem type */
386 SendDlgItemMessageW(hwndDlg, 14002, WM_SETTEXT, (WPARAM)NULL, (LPARAM)FileSystemName);
387
388 }
389
390 DriveType = GetDriveTypeW(szDrive);
391 if (DriveType == DRIVE_FIXED || DriveType == DRIVE_CDROM)
392 {
393
394 if(GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable, (PULARGE_INTEGER)&TotalNumberOfBytes, (PULARGE_INTEGER)&TotalNumberOfFreeBytes))
395 {
396 WCHAR szResult[128];
397 LONGLONG Result;
398 #ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED
399 HANDLE hVolume;
400 DWORD BytesReturned = 0;
401
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)
405 {
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);
409
410 CloseHandle(hVolume);
411 }
412 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult), hVolume, ret, LengthInformation.Length.QuadPart, BytesReturned);
413 #else
414 if (ret && StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
415 SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
416 #endif
417
418 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
419 SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
420
421 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
422 SendDlgItemMessageW(hwndDlg, 14005, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
423
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)
433 {
434 if (LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
435 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer);
436 }
437 else /* DriveType == DRIVE_CDROM) */
438 {
439 if (LoadStringW(shell32_hInstance, IDS_DRIVE_CDROM, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
440 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer);
441 }
442 }
443 }
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);
448 }
449
450
451 INT_PTR
452 CALLBACK
453 DriveGeneralDlg(
454 HWND hwndDlg,
455 UINT uMsg,
456 WPARAM wParam,
457 LPARAM lParam
458 )
459 {
460 LPPROPSHEETPAGEW ppsp;
461 LPDRAWITEMSTRUCT drawItem;
462 STARTUPINFOW si;
463 PROCESS_INFORMATION pi;
464 WCHAR * lpstr;
465 WCHAR szPath[MAX_PATH];
466 UINT length;
467 LPPSHNOTIFY lppsn;
468
469 switch(uMsg)
470 {
471 case WM_INITDIALOG:
472 ppsp = (LPPROPSHEETPAGEW)lParam;
473 if (ppsp == NULL)
474 break;
475 lpstr = (WCHAR *)ppsp->lParam;
476 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lpstr);
477 InitializeGeneralDriveDialog(hwndDlg, lpstr);
478 return TRUE;
479 case WM_DRAWITEM:
480 drawItem = (LPDRAWITEMSTRUCT)lParam;
481 if (drawItem->CtlID >= 14013 && drawItem->CtlID <= 14015)
482 {
483 PaintStaticControls(hwndDlg, drawItem);
484 return TRUE;
485 }
486 break;
487 case WM_COMMAND:
488 if (LOWORD(wParam) == 14010) /* Disk Cleanup */
489 {
490 lpstr = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
491 ZeroMemory( &si, sizeof(si) );
492 si.cb = sizeof(si);
493 ZeroMemory( &pi, sizeof(pi) );
494 if (!GetSystemDirectoryW(szPath, MAX_PATH))
495 break;
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))
501 {
502 CloseHandle(pi.hProcess);
503 CloseHandle(pi.hThread);
504 }
505 break;
506 }
507 case WM_NOTIFY:
508 lppsn = (LPPSHNOTIFY) lParam;
509 if (LOWORD(wParam) == 14000)
510 {
511 if (HIWORD(wParam) == EN_CHANGE)
512 {
513 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
514 }
515 break;
516 }
517 if (lppsn->hdr.code == PSN_APPLY)
518 {
519 lpstr = (LPWSTR)GetWindowLongPtr(hwndDlg, DWLP_USER);
520 if (lpstr && SendDlgItemMessageW(hwndDlg, 14000, WM_GETTEXT, sizeof(szPath)/sizeof(WCHAR), (LPARAM)szPath))
521 {
522 szPath[(sizeof(szPath)/sizeof(WCHAR))-1] = L'\0';
523 SetVolumeLabelW(lpstr, szPath);
524 }
525 SetWindowLongPtr( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR );
526 return TRUE;
527 }
528 break;
529
530 default:
531 break;
532 }
533
534
535 return FALSE;
536 }
537
538 INT_PTR
539 CALLBACK
540 DriveExtraDlg(
541 HWND hwndDlg,
542 UINT uMsg,
543 WPARAM wParam,
544 LPARAM lParam
545 )
546 {
547 STARTUPINFOW si;
548 PROCESS_INFORMATION pi;
549 WCHAR szPath[MAX_PATH + 10];
550 WCHAR szArg[MAX_PATH];
551 WCHAR * szDrive;
552 LPPROPSHEETPAGEW ppsp;
553 DWORD dwSize;
554 FORMAT_DRIVE_CONTEXT Context;
555
556 switch (uMsg)
557 {
558 case WM_INITDIALOG:
559 ppsp = (LPPROPSHEETPAGEW)lParam;
560 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam);
561 return TRUE;
562 case WM_COMMAND:
563 ZeroMemory( &si, sizeof(si) );
564 si.cb = sizeof(si);
565 ZeroMemory( &pi, sizeof(pi) );
566
567 szDrive = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
568 switch(LOWORD(wParam))
569 {
570 case 14000:
571 if (InitializeFmifsLibrary(&Context))
572 {
573 Context.Drive = szDrive[0];
574 DialogBoxParamW(shell32_hInstance, L"CHKDSK_DLG", hwndDlg, ChkDskDlg, (LPARAM)&Context);
575 FreeLibrary(Context.hLibrary);
576 }
577 break;
578 case 14001:
579 dwSize = sizeof(szPath);
580 if (RegGetValueW(HKEY_LOCAL_MACHINE,
581 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
582 NULL,
583 RRF_RT_REG_EXPAND_SZ,
584 NULL,
585 (PVOID)szPath,
586 &dwSize) == S_OK)
587 {
588 swprintf(szArg, szPath, szDrive[0]);
589 if (!GetSystemDirectoryW(szPath, MAX_PATH))
590 break;
591 szDrive = PathAddBackslashW(szPath);
592 if (!szDrive)
593 break;
594
595 wcscat(szDrive, L"mmc.exe");
596 if (CreateProcessW(szPath, szArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
597 {
598 CloseHandle(pi.hProcess);
599 CloseHandle(pi.hThread);
600 }
601 }
602 break;
603 case 14002:
604 dwSize = sizeof(szPath);
605 if (RegGetValueW(HKEY_LOCAL_MACHINE,
606 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
607 NULL,
608 RRF_RT_REG_EXPAND_SZ,
609 NULL,
610 (PVOID)szPath,
611 &dwSize) == S_OK)
612 {
613 if (CreateProcessW(szPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
614 {
615 CloseHandle(pi.hProcess);
616 CloseHandle(pi.hThread);
617 }
618 }
619 }
620 break;
621 }
622 return FALSE;
623 }
624
625 INT_PTR
626 CALLBACK
627 DriveHardwareDlg(
628 HWND hwndDlg,
629 UINT uMsg,
630 WPARAM wParam,
631 LPARAM lParam
632 )
633 {
634 GUID Guids[1];
635 Guids[0] = GUID_DEVCLASS_DISKDRIVE;
636
637 UNREFERENCED_PARAMETER(lParam);
638 UNREFERENCED_PARAMETER(wParam);
639
640 switch(uMsg)
641 {
642 case WM_INITDIALOG:
643 /* create the hardware page */
644 DeviceCreateHardwarePageEx(hwndDlg,
645 Guids,
646 sizeof(Guids) / sizeof(Guids[0]),
647 0);
648 break;
649 }
650
651 return FALSE;
652 }
653
654 static
655 const
656 struct
657 {
658 LPSTR resname;
659 DLGPROC dlgproc;
660 UINT DriveType;
661 } PropPages[] =
662 {
663 { "DRIVE_GENERAL_DLG", DriveGeneralDlg, -1},
664 { "DRIVE_EXTRA_DLG", DriveExtraDlg, DRIVE_FIXED},
665 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg, -1},
666 };
667
668 HRESULT
669 CALLBACK
670 AddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam)
671 {
672 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
673 if (ppsh != NULL && ppsh->nPages < MAX_PROPERTY_SHEET_PAGE)
674 {
675 ppsh->phpage[ppsh->nPages++] = hpage;
676 return TRUE;
677 }
678 return FALSE;
679 }
680
681 BOOL
682 SH_ShowDriveProperties(WCHAR * drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl)
683 {
684 HPSXA hpsx = NULL;
685 HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
686 PROPSHEETHEADERW psh;
687 BOOL ret;
688 UINT i;
689 WCHAR szName[MAX_PATH+6];
690 DWORD dwMaxComponent, dwFileSysFlags;
691 IDataObject * pDataObj = NULL;
692 UINT DriveType;
693
694 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
695 psh.dwSize = sizeof(PROPSHEETHEADERW);
696 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
697 psh.hwndParent = NULL;
698 psh.nStartPage = 0;
699 psh.phpage = hpsp;
700
701 if (GetVolumeInformationW(drive, szName, sizeof(szName)/sizeof(WCHAR), NULL, &dwMaxComponent,
702 &dwFileSysFlags, NULL, 0))
703 {
704 psh.pszCaption = szName;
705 psh.dwFlags |= PSH_PROPTITLE;
706 if (!wcslen(szName))
707 {
708 /* FIXME
709 * check if disk is a really a local hdd
710 */
711 i = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szName, sizeof(szName)/sizeof(WCHAR)-6);
712 if (i > 0 && i < (sizeof(szName)/sizeof(WCHAR)) - 6)
713 {
714 szName[i] = L' ';
715 szName[i+1] = L'(';
716 wcscpy(&szName[i+2], drive);
717 szName[i+4] = L')';
718 szName[i+5] = L'\0';
719 }
720 }
721 }
722
723 DriveType = GetDriveTypeW(drive);
724 for (i = 0; i < DRIVE_PROPERTY_PAGES; i++)
725 {
726 if (PropPages[i].DriveType == (UINT)-1 || (PropPages[i].DriveType != (UINT)-1 && PropPages[i].DriveType == DriveType))
727 {
728 HPROPSHEETPAGE hprop = SH_CreatePropertySheetPage(PropPages[i].resname, PropPages[i].dlgproc, (LPARAM)drive, NULL);
729 if (hprop)
730 {
731 hpsp[psh.nPages] = hprop;
732 psh.nPages++;
733 }
734 }
735 }
736
737 if (SHCreateDataObject(pidlFolder, 1, apidl, NULL, &IID_IDataObject, (void**)&pDataObj) == S_OK)
738 {
739 hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", MAX_PROPERTY_SHEET_PAGE-DRIVE_PROPERTY_PAGES, pDataObj);
740 if (hpsx)
741 {
742 SHAddFromPropSheetExtArray(hpsx, (LPFNADDPROPSHEETPAGE)AddPropSheetPageProc, (LPARAM)&psh);
743 }
744 }
745
746 ret = PropertySheetW(&psh);
747 if (pDataObj)
748 IDataObject_Release(pDataObj);
749
750 if (hpsx)
751 SHDestroyPropSheetExtArray(hpsx);
752
753 if (ret < 0)
754 return FALSE;
755 else
756 return TRUE;
757 }
758
759 BOOL
760 GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes)
761 {
762 DWORD ClusterSize;
763
764 if (!wcsicmp(szFs, L"FAT16") ||
765 !wcsicmp(szFs, L"FAT")) //REACTOS HACK
766 {
767 if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
768 ClusterSize = 2048;
769 else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
770 ClusterSize = 512;
771 else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
772 ClusterSize = 1024;
773 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
774 ClusterSize = 2048;
775 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
776 ClusterSize = 4096;
777 else if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
778 ClusterSize = 8192;
779 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
780 ClusterSize = 16384;
781 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
782 ClusterSize = 32768;
783 else if (TotalNumberOfBytes->QuadPart <= (4096LL * 1024LL * 1024LL))
784 ClusterSize = 8192;
785 else
786 return FALSE;
787 }
788 else if (!wcsicmp(szFs, L"FAT32"))
789 {
790 if (TotalNumberOfBytes->QuadPart <=(64 * 1024 * 1024))
791 ClusterSize = 512;
792 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
793 ClusterSize = 1024;
794 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
795 ClusterSize = 2048;
796 else if (TotalNumberOfBytes->QuadPart <= (8192LL * 1024LL * 1024LL))
797 ClusterSize = 2048;
798 else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
799 ClusterSize = 8192;
800 else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
801 ClusterSize = 16384;
802 else
803 return FALSE;
804 }
805 else if (!wcsicmp(szFs, L"NTFS"))
806 {
807 if (TotalNumberOfBytes->QuadPart <=(512 * 1024 * 1024))
808 ClusterSize = 512;
809 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
810 ClusterSize = 1024;
811 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
812 ClusterSize = 2048;
813 else
814 ClusterSize = 2048;
815 }
816 else
817 return FALSE;
818
819 *pClusterSize = ClusterSize;
820 return TRUE;
821 }
822
823
824 VOID
825 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
826 {
827 WCHAR szFs[100] = {0};
828 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
829 INT iSelIndex;
830 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
831 DWORD ClusterSize;
832 LRESULT lIndex;
833 HWND hDlgCtrl;
834
835 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
836 iSelIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
837 if (iSelIndex == CB_ERR)
838 return;
839
840 if (SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFs) == CB_ERR)
841 return;
842
843 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
844 szDrive[0] = pContext->Drive + 'A';
845
846 if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
847 return;
848
849 if (!wcsicmp(szFs, L"FAT16") ||
850 !wcsicmp(szFs, L"FAT")) //REACTOS HACK
851 {
852 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
853 {
854 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes.QuadPart);
855 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
856 return;
857 }
858
859 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
860 {
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);
868 }
869 }
870 else if (!wcsicmp(szFs, L"FAT32"))
871 {
872 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
873 {
874 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes.QuadPart);
875 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
876 return;
877 }
878
879 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
880 {
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);
888 }
889 }
890 else if (!wcsicmp(szFs, L"NTFS"))
891 {
892 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
893 {
894 TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes.QuadPart);
895 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
896 return;
897 }
898
899 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
900 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
901 {
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);
908 }
909 ClusterSize = 512;
910 for (lIndex = 0; lIndex < 4; lIndex++)
911 {
912 TotalNumberOfBytes.QuadPart = ClusterSize;
913 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szFs, sizeof(szFs)/sizeof(WCHAR)))
914 {
915 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
916 if (lIndex != CB_ERR)
917 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
918 }
919 ClusterSize *= 2;
920 }
921 }
922 else
923 {
924 FIXME("unknown fs\n");
925 SendDlgItemMessageW(hwndDlg, 28680, CB_RESETCONTENT, iSelIndex, 0);
926 return;
927 }
928 }
929
930 VOID
931 InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
932 {
933 WCHAR szText[120];
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;
941 BOOLEAN Latest;
942 HWND hDlgCtrl;
943
944 Length = GetWindowTextW(hwndDlg, szText, sizeof(szText)/sizeof(WCHAR));
945 if (Length < 0)
946 Length = 0;
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)))
949 {
950 szText[Length] = L' ';
951 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
952 TempLength = wcslen(&szText[Length+1]);
953 if (!TempLength)
954 {
955 /* load default volume label */
956 TempLength = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2);
957 }
958 else
959 {
960 /* set volume label */
961 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
962 SendDlgItemMessageW(hwndDlg, 28679, WM_SETTEXT, 0, (LPARAM)&szText[Length+1]);
963 }
964 Length += TempLength + 1;
965 }
966
967 if (Length + 4 < (sizeof(szText)/sizeof(WCHAR)))
968 {
969 szText[Length] = L' ';
970 szText[Length+1] = L'(';
971 szText[Length+2] = szDrive[0];
972 szText[Length+3] = L')';
973 Length +=4;
974 }
975
976 if (Length < (sizeof(szText)/sizeof(WCHAR)))
977 szText[Length] = L'\0';
978 else
979 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
980
981 /* set window text */
982 SetWindowTextW(hwndDlg, szText);
983
984 if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
985 {
986 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szText, sizeof(szText)/sizeof(WCHAR)))
987 {
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);
992 }
993 }
994
995 if (pContext->Options & SHFMT_OPT_FULL)
996 {
997 /* check quick format button */
998 SendDlgItemMessageW(hwndDlg, 28674, BM_SETCHECK, BST_CHECKED, 0);
999 }
1000
1001 /* enumerate all available filesystems */
1002 dwIndex = 0;
1003 dwDefault = 0;
1004 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
1005
1006 while(pContext->QueryAvailableFileSystemFormat(dwIndex, szText, &uMajor, &uMinor, &Latest))
1007 {
1008 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
1009 if (!wcsicmp(szText, szFs))
1010 dwDefault = dwIndex;
1011
1012 SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szText);
1013 dwIndex++;
1014 }
1015
1016 if (!dwIndex)
1017 {
1018 ERR("no filesystem providers\n");
1019 return;
1020 }
1021
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);
1028 }
1029
1030 HWND FormatDrvDialog = NULL;
1031 BOOLEAN bSuccess = FALSE;
1032
1033
1034 BOOLEAN
1035 NTAPI
1036 FormatExCB(
1037 IN CALLBACKCOMMAND Command,
1038 IN ULONG SubAction,
1039 IN PVOID ActionInfo)
1040 {
1041 PDWORD Progress;
1042 PBOOLEAN pSuccess;
1043 switch(Command)
1044 {
1045 case PROGRESS:
1046 Progress = (PDWORD)ActionInfo;
1047 SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, (WPARAM)*Progress, 0);
1048 break;
1049 case DONE:
1050 pSuccess = (PBOOLEAN)ActionInfo;
1051 bSuccess = (*pSuccess);
1052 break;
1053
1054 case VOLUMEINUSE:
1055 case INSUFFICIENTRIGHTS:
1056 case FSNOTSUPPORTED:
1057 case CLUSTERSIZETOOSMALL:
1058 bSuccess = FALSE;
1059 FIXME("\n");
1060 break;
1061
1062 default:
1063 break;
1064 }
1065
1066 return TRUE;
1067 }
1068
1069
1070
1071
1072
1073 VOID
1074 FormatDrive(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
1075 {
1076 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
1077 WCHAR szFileSys[40] = {0};
1078 WCHAR szLabel[40] = {0};
1079 INT iSelIndex;
1080 UINT Length;
1081 HWND hDlgCtrl;
1082 BOOL QuickFormat;
1083 DWORD ClusterSize;
1084
1085 /* set volume path */
1086 szDrive[0] = pContext->Drive;
1087
1088 /* get filesystem */
1089 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
1090 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
1091 if (iSelIndex == CB_ERR)
1092 {
1093 FIXME("\n");
1094 return;
1095 }
1096 Length = SendMessageW(hDlgCtrl, CB_GETLBTEXTLEN, iSelIndex, 0);
1097 if (Length == CB_ERR || Length + 1> sizeof(szFileSys)/sizeof(WCHAR))
1098 {
1099 FIXME("\n");
1100 return;
1101 }
1102
1103 /* retrieve the file system */
1104 SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFileSys);
1105 szFileSys[(sizeof(szFileSys)/sizeof(WCHAR))-1] = L'\0';
1106
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))
1111 {
1112 FIXME("\n");
1113 return;
1114 }
1115 SendMessageW(hDlgCtrl, WM_GETTEXT, sizeof(szLabel)/sizeof(WCHAR), (LPARAM)szLabel);
1116 szLabel[(sizeof(szLabel)/sizeof(WCHAR))-1] = L'\0';
1117
1118 /* check for quickformat */
1119 if (SendDlgItemMessageW(hwndDlg, 28674, BM_GETCHECK, 0, 0) == BST_CHECKED)
1120 QuickFormat = TRUE;
1121 else
1122 QuickFormat = FALSE;
1123
1124 /* get the cluster size */
1125 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
1126 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
1127 if (iSelIndex == CB_ERR)
1128 {
1129 FIXME("\n");
1130 return;
1131 }
1132 ClusterSize = SendMessageW(hDlgCtrl, CB_GETITEMDATA, iSelIndex, 0);
1133 if (ClusterSize == CB_ERR)
1134 {
1135 FIXME("\n");
1136 return;
1137 }
1138
1139 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
1140 ShowWindow(hDlgCtrl, SW_SHOW);
1141 SendMessageW(hDlgCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
1142 bSuccess = FALSE;
1143
1144 /* FIXME
1145 * will cause display problems
1146 * when performing more than one format
1147 */
1148 FormatDrvDialog = hwndDlg;
1149
1150 pContext->FormatEx(szDrive,
1151 FMIFS_HARDDISK, /* FIXME */
1152 szFileSys,
1153 szLabel,
1154 QuickFormat,
1155 ClusterSize,
1156 FormatExCB);
1157
1158 ShowWindow(hDlgCtrl, SW_HIDE);
1159 FormatDrvDialog = NULL;
1160 if (!bSuccess)
1161 {
1162 pContext->Result = SHFMT_ERROR;
1163 }
1164 else if (QuickFormat)
1165 {
1166 pContext->Result = SHFMT_OPT_FULL;
1167 }
1168 else
1169 {
1170 pContext->Result = FALSE;
1171 }
1172 }
1173
1174
1175 BOOL
1176 CALLBACK
1177 FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1178 {
1179 PFORMAT_DRIVE_CONTEXT pContext;
1180
1181 switch(uMsg)
1182 {
1183 case WM_INITDIALOG:
1184 InitializeFormatDriveDlg(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
1185 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
1186 return TRUE;
1187 case WM_COMMAND:
1188 switch(LOWORD(wParam))
1189 {
1190 case IDOK:
1191 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1192 FormatDrive(hwndDlg, pContext);
1193 break;
1194 case IDCANCEL:
1195 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1196 EndDialog(hwndDlg, pContext->Result);
1197 break;
1198 case 28677: // filesystem combo
1199 if (HIWORD(wParam) == CBN_SELENDOK)
1200 {
1201 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1202 InsertDefaultClusterSizeForFs(hwndDlg, pContext);
1203 }
1204 break;
1205 }
1206 }
1207 return FALSE;
1208 }
1209
1210
1211 BOOL
1212 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext)
1213 {
1214 INITIALIZE_FMIFS InitFmifs;
1215 BOOLEAN ret;
1216 HMODULE hLibrary;
1217
1218 hLibrary = pContext->hLibrary = LoadLibraryW(L"fmifs.dll");
1219 if(!hLibrary)
1220 {
1221 ERR("failed to load fmifs.dll\n");
1222 return FALSE;
1223 }
1224
1225 InitFmifs = (INITIALIZE_FMIFS)GetProcAddress(hLibrary, "InitializeFmIfs");
1226 if (!InitFmifs)
1227 {
1228 ERR("InitializeFmIfs export is missing\n");
1229 FreeLibrary(hLibrary);
1230 return FALSE;
1231 }
1232
1233 ret = (*InitFmifs)(NULL, DLL_PROCESS_ATTACH, NULL);
1234 if (!ret)
1235 {
1236 ERR("fmifs failed to initialize\n");
1237 FreeLibrary(hLibrary);
1238 return FALSE;
1239 }
1240
1241 pContext->QueryAvailableFileSystemFormat = (QUERY_AVAILABLEFSFORMAT)GetProcAddress(hLibrary, "QueryAvailableFileSystemFormat");
1242 if (!pContext->QueryAvailableFileSystemFormat)
1243 {
1244 ERR("QueryAvailableFileSystemFormat export is missing\n");
1245 FreeLibrary(hLibrary);
1246 return FALSE;
1247 }
1248
1249 pContext->FormatEx = (FORMAT_EX) GetProcAddress(hLibrary, "FormatEx");
1250 if (!pContext->FormatEx)
1251 {
1252 ERR("FormatEx export is missing\n");
1253 FreeLibrary(hLibrary);
1254 return FALSE;
1255 }
1256
1257 pContext->EnableVolumeCompression = (ENABLEVOLUMECOMPRESSION) GetProcAddress(hLibrary, "EnableVolumeCompression");
1258 if (!pContext->FormatEx)
1259 {
1260 ERR("EnableVolumeCompression export is missing\n");
1261 FreeLibrary(hLibrary);
1262 return FALSE;
1263 }
1264
1265 pContext->Chkdsk = (CHKDSK) GetProcAddress(hLibrary, "Chkdsk");
1266 if (!pContext->Chkdsk)
1267 {
1268 ERR("Chkdsk export is missing\n");
1269 FreeLibrary(hLibrary);
1270 return FALSE;
1271 }
1272
1273 return TRUE;
1274 }
1275
1276 /*************************************************************************
1277 * SHFormatDrive (SHELL32.@)
1278 */
1279
1280 DWORD
1281 WINAPI
1282 SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options)
1283 {
1284 FORMAT_DRIVE_CONTEXT Context;
1285 int result;
1286
1287 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd, drive, fmtID, options);
1288
1289 if (!InitializeFmifsLibrary(&Context))
1290 {
1291 ERR("failed to initialize fmifs\n");
1292 return SHFMT_NOFORMAT;
1293 }
1294
1295 Context.Drive = drive;
1296 Context.Options = options;
1297
1298 result = DialogBoxParamW(shell32_hInstance, L"FORMAT_DLG", hwnd, FormatDriveDlg, (LPARAM)&Context);
1299
1300 FreeLibrary(Context.hLibrary);
1301 return result;
1302 }
1303
1304