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