[CMAKE]
[reactos.git] / 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 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(TotalNumberOfBytes.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
407 SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
408
409 CloseHandle(hVolume);
410 }
411
412 TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult), hVolume, ret, TotalNumberOfBytes.QuadPart, BytesReturned);
413
414 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
415 SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
416
417 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR)))
418 SendDlgItemMessageW(hwndDlg, 14005, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult);
419
420 Result = GetFreeBytesShare(TotalNumberOfFreeBytes.QuadPart, TotalNumberOfBytes.QuadPart);
421 /* set free bytes percentage */
422 swprintf(szResult, L"%02d%%", Result);
423 SendDlgItemMessageW(hwndDlg, 14006, WM_SETTEXT, (WPARAM)0, (LPARAM)szResult);
424 /* store used share amount */
425 Result = 100 - Result;
426 swprintf(szResult, L"%02d%%", Result);
427 SendDlgItemMessageW(hwndDlg, 14004, WM_SETTEXT, (WPARAM)0, (LPARAM)szResult);
428 if (DriveType == DRIVE_FIXED)
429 {
430 if (LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
431 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer);
432 }
433 else /* DriveType == DRIVE_CDROM) */
434 {
435 if (LoadStringW(shell32_hInstance, IDS_DRIVE_CDROM, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
436 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer);
437 }
438 }
439 }
440 /* set drive description */
441 SendDlgItemMessageW(hwndDlg, 14009, WM_GETTEXT, (WPARAM)50, (LPARAM)szFormat);
442 swprintf(szBuffer, szFormat, szDrive);
443 SendDlgItemMessageW(hwndDlg, 14009, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szBuffer);
444 }
445
446
447 INT_PTR
448 CALLBACK
449 DriveGeneralDlg(
450 HWND hwndDlg,
451 UINT uMsg,
452 WPARAM wParam,
453 LPARAM lParam
454 )
455 {
456 LPPROPSHEETPAGEW ppsp;
457 LPDRAWITEMSTRUCT drawItem;
458 STARTUPINFOW si;
459 PROCESS_INFORMATION pi;
460 WCHAR * lpstr;
461 WCHAR szPath[MAX_PATH];
462 UINT length;
463 LPPSHNOTIFY lppsn;
464
465 switch(uMsg)
466 {
467 case WM_INITDIALOG:
468 ppsp = (LPPROPSHEETPAGEW)lParam;
469 if (ppsp == NULL)
470 break;
471 lpstr = (WCHAR *)ppsp->lParam;
472 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lpstr);
473 InitializeGeneralDriveDialog(hwndDlg, lpstr);
474 return TRUE;
475 case WM_DRAWITEM:
476 drawItem = (LPDRAWITEMSTRUCT)lParam;
477 if (drawItem->CtlID >= 14013 && drawItem->CtlID <= 14015)
478 {
479 PaintStaticControls(hwndDlg, drawItem);
480 return TRUE;
481 }
482 break;
483 case WM_COMMAND:
484 if (LOWORD(wParam) == 14010) /* Disk Cleanup */
485 {
486 lpstr = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
487 ZeroMemory( &si, sizeof(si) );
488 si.cb = sizeof(si);
489 ZeroMemory( &pi, sizeof(pi) );
490 if (!GetSystemDirectoryW(szPath, MAX_PATH))
491 break;
492 wcscat(szPath, L"\\cleanmgr.exe /D ");
493 length = wcslen(szPath);
494 szPath[length] = lpstr[0];
495 szPath[length+1] = L'\0';
496 if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
497 {
498 CloseHandle(pi.hProcess);
499 CloseHandle(pi.hThread);
500 }
501 break;
502 }
503 case WM_NOTIFY:
504 lppsn = (LPPSHNOTIFY) lParam;
505 if (LOWORD(wParam) == 14000)
506 {
507 if (HIWORD(wParam) == EN_CHANGE)
508 {
509 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
510 }
511 break;
512 }
513 if (lppsn->hdr.code == PSN_APPLY)
514 {
515 lpstr = (LPWSTR)GetWindowLongPtr(hwndDlg, DWLP_USER);
516 if (lpstr && SendDlgItemMessageW(hwndDlg, 14000, WM_GETTEXT, sizeof(szPath)/sizeof(WCHAR), (LPARAM)szPath))
517 {
518 szPath[(sizeof(szPath)/sizeof(WCHAR))-1] = L'\0';
519 SetVolumeLabelW(lpstr, szPath);
520 }
521 SetWindowLongPtr( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR );
522 return TRUE;
523 }
524 break;
525
526 default:
527 break;
528 }
529
530
531 return FALSE;
532 }
533
534 INT_PTR
535 CALLBACK
536 DriveExtraDlg(
537 HWND hwndDlg,
538 UINT uMsg,
539 WPARAM wParam,
540 LPARAM lParam
541 )
542 {
543 STARTUPINFOW si;
544 PROCESS_INFORMATION pi;
545 WCHAR szPath[MAX_PATH + 10];
546 WCHAR szArg[MAX_PATH];
547 WCHAR * szDrive;
548 LPPROPSHEETPAGEW ppsp;
549 DWORD dwSize;
550 FORMAT_DRIVE_CONTEXT Context;
551
552 switch (uMsg)
553 {
554 case WM_INITDIALOG:
555 ppsp = (LPPROPSHEETPAGEW)lParam;
556 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam);
557 return TRUE;
558 case WM_COMMAND:
559 ZeroMemory( &si, sizeof(si) );
560 si.cb = sizeof(si);
561 ZeroMemory( &pi, sizeof(pi) );
562
563 szDrive = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);
564 switch(LOWORD(wParam))
565 {
566 case 14000:
567 if (InitializeFmifsLibrary(&Context))
568 {
569 Context.Drive = szDrive[0];
570 DialogBoxParamW(shell32_hInstance, L"CHKDSK_DLG", hwndDlg, ChkDskDlg, (LPARAM)&Context);
571 FreeLibrary(Context.hLibrary);
572 }
573 break;
574 case 14001:
575 dwSize = sizeof(szPath);
576 if (RegGetValueW(HKEY_LOCAL_MACHINE,
577 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
578 NULL,
579 RRF_RT_REG_EXPAND_SZ,
580 NULL,
581 (PVOID)szPath,
582 &dwSize) == S_OK)
583 {
584 swprintf(szArg, szPath, szDrive[0]);
585 if (!GetSystemDirectoryW(szPath, MAX_PATH))
586 break;
587 szDrive = PathAddBackslashW(szPath);
588 if (!szDrive)
589 break;
590
591 wcscat(szDrive, L"mmc.exe");
592 if (CreateProcessW(szPath, szArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
593 {
594 CloseHandle(pi.hProcess);
595 CloseHandle(pi.hThread);
596 }
597 }
598 break;
599 case 14002:
600 dwSize = sizeof(szPath);
601 if (RegGetValueW(HKEY_LOCAL_MACHINE,
602 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
603 NULL,
604 RRF_RT_REG_EXPAND_SZ,
605 NULL,
606 (PVOID)szPath,
607 &dwSize) == S_OK)
608 {
609 if (CreateProcessW(szPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
610 {
611 CloseHandle(pi.hProcess);
612 CloseHandle(pi.hThread);
613 }
614 }
615 }
616 break;
617 }
618 return FALSE;
619 }
620
621 INT_PTR
622 CALLBACK
623 DriveHardwareDlg(
624 HWND hwndDlg,
625 UINT uMsg,
626 WPARAM wParam,
627 LPARAM lParam
628 )
629 {
630 GUID Guids[1];
631 Guids[0] = GUID_DEVCLASS_DISKDRIVE;
632
633 UNREFERENCED_PARAMETER(lParam);
634 UNREFERENCED_PARAMETER(wParam);
635
636 switch(uMsg)
637 {
638 case WM_INITDIALOG:
639 /* create the hardware page */
640 DeviceCreateHardwarePageEx(hwndDlg,
641 Guids,
642 sizeof(Guids) / sizeof(Guids[0]),
643 0);
644 break;
645 }
646
647 return FALSE;
648 }
649
650 static
651 const
652 struct
653 {
654 LPSTR resname;
655 DLGPROC dlgproc;
656 UINT DriveType;
657 } PropPages[] =
658 {
659 { "DRIVE_GENERAL_DLG", DriveGeneralDlg, -1},
660 { "DRIVE_EXTRA_DLG", DriveExtraDlg, DRIVE_FIXED},
661 { "DRIVE_HARDWARE_DLG", DriveHardwareDlg, -1},
662 };
663
664 HRESULT
665 CALLBACK
666 AddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam)
667 {
668 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
669 if (ppsh != NULL && ppsh->nPages < MAX_PROPERTY_SHEET_PAGE)
670 {
671 ppsh->phpage[ppsh->nPages++] = hpage;
672 return TRUE;
673 }
674 return FALSE;
675 }
676
677 BOOL
678 SH_ShowDriveProperties(WCHAR * drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl)
679 {
680 HPSXA hpsx = NULL;
681 HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
682 PROPSHEETHEADERW psh;
683 BOOL ret;
684 UINT i;
685 WCHAR szName[MAX_PATH+6];
686 DWORD dwMaxComponent, dwFileSysFlags;
687 IDataObject * pDataObj = NULL;
688 UINT DriveType;
689
690 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
691 psh.dwSize = sizeof(PROPSHEETHEADERW);
692 //psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
693 psh.hwndParent = NULL;
694 psh.nStartPage = 0;
695 psh.phpage = hpsp;
696
697 if (GetVolumeInformationW(drive, szName, sizeof(szName)/sizeof(WCHAR), NULL, &dwMaxComponent,
698 &dwFileSysFlags, NULL, 0))
699 {
700 psh.pszCaption = szName;
701 psh.dwFlags |= PSH_PROPTITLE;
702 if (!wcslen(szName))
703 {
704 /* FIXME
705 * check if disk is a really a local hdd
706 */
707 i = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szName, sizeof(szName)/sizeof(WCHAR)-6);
708 if (i > 0 && i < (sizeof(szName)/sizeof(WCHAR)) - 6)
709 {
710 szName[i] = L' ';
711 szName[i+1] = L'(';
712 wcscpy(&szName[i+2], drive);
713 szName[i+4] = L')';
714 szName[i+5] = L'\0';
715 }
716 }
717 }
718
719 DriveType = GetDriveTypeW(drive);
720 for (i = 0; i < DRIVE_PROPERTY_PAGES; i++)
721 {
722 if (PropPages[i].DriveType == (UINT)-1 || (PropPages[i].DriveType != (UINT)-1 && PropPages[i].DriveType == DriveType))
723 {
724 HPROPSHEETPAGE hprop = SH_CreatePropertySheetPage(PropPages[i].resname, PropPages[i].dlgproc, (LPARAM)drive, NULL);
725 if (hprop)
726 {
727 hpsp[psh.nPages] = hprop;
728 psh.nPages++;
729 }
730 }
731 }
732
733 if (SHCreateDataObject(pidlFolder, 1, apidl, NULL, &IID_IDataObject, (void**)&pDataObj) == S_OK)
734 {
735 hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", MAX_PROPERTY_SHEET_PAGE-DRIVE_PROPERTY_PAGES, pDataObj);
736 if (hpsx)
737 {
738 SHAddFromPropSheetExtArray(hpsx, (LPFNADDPROPSHEETPAGE)AddPropSheetPageProc, (LPARAM)&psh);
739 }
740 }
741
742 ret = PropertySheetW(&psh);
743 if (pDataObj)
744 IDataObject_Release(pDataObj);
745
746 if (hpsx)
747 SHDestroyPropSheetExtArray(hpsx);
748
749 if (ret < 0)
750 return FALSE;
751 else
752 return TRUE;
753 }
754
755 BOOL
756 GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes)
757 {
758 DWORD ClusterSize;
759
760 if (!wcsicmp(szFs, L"FAT16") ||
761 !wcsicmp(szFs, L"FAT")) //REACTOS HACK
762 {
763 if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
764 ClusterSize = 2048;
765 else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
766 ClusterSize = 512;
767 else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
768 ClusterSize = 1024;
769 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
770 ClusterSize = 2048;
771 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
772 ClusterSize = 4096;
773 else if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
774 ClusterSize = 8192;
775 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
776 ClusterSize = 16384;
777 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
778 ClusterSize = 32768;
779 else if (TotalNumberOfBytes->QuadPart <= (4096LL * 1024LL * 1024LL))
780 ClusterSize = 8192;
781 else
782 return FALSE;
783 }
784 else if (!wcsicmp(szFs, L"FAT32"))
785 {
786 if (TotalNumberOfBytes->QuadPart <=(64 * 1024 * 1024))
787 ClusterSize = 512;
788 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
789 ClusterSize = 1024;
790 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
791 ClusterSize = 2048;
792 else if (TotalNumberOfBytes->QuadPart <= (8192LL * 1024LL * 1024LL))
793 ClusterSize = 2048;
794 else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
795 ClusterSize = 8192;
796 else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
797 ClusterSize = 16384;
798 else
799 return FALSE;
800 }
801 else if (!wcsicmp(szFs, L"NTFS"))
802 {
803 if (TotalNumberOfBytes->QuadPart <=(512 * 1024 * 1024))
804 ClusterSize = 512;
805 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
806 ClusterSize = 1024;
807 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
808 ClusterSize = 2048;
809 else
810 ClusterSize = 2048;
811 }
812 else
813 return FALSE;
814
815 *pClusterSize = ClusterSize;
816 return TRUE;
817 }
818
819
820 VOID
821 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
822 {
823 WCHAR szFs[100] = {0};
824 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
825 INT iSelIndex;
826 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
827 DWORD ClusterSize;
828 LRESULT lIndex;
829 HWND hDlgCtrl;
830
831 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
832 iSelIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
833 if (iSelIndex == CB_ERR)
834 return;
835
836 if (SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFs) == CB_ERR)
837 return;
838
839 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
840 szDrive[0] = pContext->Drive + 'A';
841
842 if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
843 return;
844
845 if (!wcsicmp(szFs, L"FAT16") ||
846 !wcsicmp(szFs, L"FAT")) //REACTOS HACK
847 {
848 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
849 {
850 TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes.QuadPart);
851 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
852 return;
853 }
854
855 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
856 {
857 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
858 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
859 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
860 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
861 if (lIndex != CB_ERR)
862 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
863 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
864 }
865 }
866 else if (!wcsicmp(szFs, L"FAT32"))
867 {
868 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
869 {
870 TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes.QuadPart);
871 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
872 return;
873 }
874
875 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
876 {
877 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
878 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
879 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
880 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
881 if (lIndex != CB_ERR)
882 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
883 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
884 }
885 }
886 else if (!wcsicmp(szFs, L"NTFS"))
887 {
888 if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))
889 {
890 TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes.QuadPart);
891 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
892 return;
893 }
894
895 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
896 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))
897 {
898 szFs[(sizeof(szFs)/sizeof(WCHAR))-1] = L'\0';
899 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
900 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
901 if (lIndex != CB_ERR)
902 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
903 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
904 }
905 ClusterSize = 512;
906 for (lIndex = 0; lIndex < 4; lIndex++)
907 {
908 TotalNumberOfBytes.QuadPart = ClusterSize;
909 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szFs, sizeof(szFs)/sizeof(WCHAR)))
910 {
911 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szFs);
912 if (lIndex != CB_ERR)
913 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
914 }
915 ClusterSize *= 2;
916 }
917 }
918 else
919 {
920 FIXME("unknown fs\n");
921 SendDlgItemMessageW(hwndDlg, 28680, CB_RESETCONTENT, iSelIndex, 0);
922 return;
923 }
924 }
925
926 VOID
927 InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
928 {
929 WCHAR szText[120];
930 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
931 WCHAR szFs[30] = {0};
932 INT Length, TempLength;
933 DWORD dwSerial, dwMaxComp, dwFileSys;
934 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
935 DWORD dwIndex, dwDefault;
936 UCHAR uMinor, uMajor;
937 BOOLEAN Latest;
938 HWND hDlgCtrl;
939
940 Length = GetWindowTextW(hwndDlg, szText, sizeof(szText)/sizeof(WCHAR));
941 if (Length < 0)
942 Length = 0;
943 szDrive[0] = pContext->Drive + L'A';
944 if (GetVolumeInformationW(szDrive, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2, &dwSerial, &dwMaxComp, &dwFileSys, szFs, sizeof(szFs)/sizeof(WCHAR)))
945 {
946 szText[Length] = L' ';
947 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
948 TempLength = wcslen(&szText[Length+1]);
949 if (!TempLength)
950 {
951 /* load default volume label */
952 TempLength = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2);
953 }
954 else
955 {
956 /* set volume label */
957 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
958 SendDlgItemMessageW(hwndDlg, 28679, WM_SETTEXT, 0, (LPARAM)&szText[Length+1]);
959 }
960 Length += TempLength + 1;
961 }
962
963 if (Length + 4 < (sizeof(szText)/sizeof(WCHAR)))
964 {
965 szText[Length] = L' ';
966 szText[Length+1] = L'(';
967 szText[Length+2] = szDrive[0];
968 szText[Length+3] = L')';
969 Length +=4;
970 }
971
972 if (Length < (sizeof(szText)/sizeof(WCHAR)))
973 szText[Length] = L'\0';
974 else
975 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
976
977 /* set window text */
978 SetWindowTextW(hwndDlg, szText);
979
980 if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
981 {
982 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szText, sizeof(szText)/sizeof(WCHAR)))
983 {
984 /* add drive capacity */
985 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
986 SendDlgItemMessageW(hwndDlg, 28673, CB_ADDSTRING, 0, (LPARAM)szText);
987 SendDlgItemMessageW(hwndDlg, 28673, CB_SETCURSEL, 0, (LPARAM)0);
988 }
989 }
990
991 if (pContext->Options & SHFMT_OPT_FULL)
992 {
993 /* check quick format button */
994 SendDlgItemMessageW(hwndDlg, 28674, BM_SETCHECK, BST_CHECKED, 0);
995 }
996
997 /* enumerate all available filesystems */
998 dwIndex = 0;
999 dwDefault = 0;
1000 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
1001
1002 while(pContext->QueryAvailableFileSystemFormat(dwIndex, szText, &uMajor, &uMinor, &Latest))
1003 {
1004 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
1005 if (!wcsicmp(szText, szFs))
1006 dwDefault = dwIndex;
1007
1008 SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)szText);
1009 dwIndex++;
1010 }
1011
1012 if (!dwIndex)
1013 {
1014 ERR("no filesystem providers\n");
1015 return;
1016 }
1017
1018 /* select default filesys */
1019 SendMessageW(hDlgCtrl, CB_SETCURSEL, dwDefault, 0);
1020 /* setup cluster combo */
1021 InsertDefaultClusterSizeForFs(hwndDlg, pContext);
1022 /* hide progress control */
1023 ShowWindow(GetDlgItem(hwndDlg, 28678), SW_HIDE);
1024 }
1025
1026 HWND FormatDrvDialog = NULL;
1027 BOOLEAN bSuccess = FALSE;
1028
1029
1030 BOOLEAN
1031 NTAPI
1032 FormatExCB(
1033 IN CALLBACKCOMMAND Command,
1034 IN ULONG SubAction,
1035 IN PVOID ActionInfo)
1036 {
1037 PDWORD Progress;
1038 PBOOLEAN pSuccess;
1039 switch(Command)
1040 {
1041 case PROGRESS:
1042 Progress = (PDWORD)ActionInfo;
1043 SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, (WPARAM)*Progress, 0);
1044 break;
1045 case DONE:
1046 pSuccess = (PBOOLEAN)ActionInfo;
1047 bSuccess = (*pSuccess);
1048 break;
1049
1050 case VOLUMEINUSE:
1051 case INSUFFICIENTRIGHTS:
1052 case FSNOTSUPPORTED:
1053 case CLUSTERSIZETOOSMALL:
1054 bSuccess = FALSE;
1055 FIXME("\n");
1056 break;
1057
1058 default:
1059 break;
1060 }
1061
1062 return TRUE;
1063 }
1064
1065
1066
1067
1068
1069 VOID
1070 FormatDrive(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
1071 {
1072 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
1073 WCHAR szFileSys[40] = {0};
1074 WCHAR szLabel[40] = {0};
1075 INT iSelIndex;
1076 UINT Length;
1077 HWND hDlgCtrl;
1078 BOOL QuickFormat;
1079 DWORD ClusterSize;
1080
1081 /* set volume path */
1082 szDrive[0] = pContext->Drive;
1083
1084 /* get filesystem */
1085 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
1086 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
1087 if (iSelIndex == CB_ERR)
1088 {
1089 FIXME("\n");
1090 return;
1091 }
1092 Length = SendMessageW(hDlgCtrl, CB_GETLBTEXTLEN, iSelIndex, 0);
1093 if (Length == CB_ERR || Length + 1> sizeof(szFileSys)/sizeof(WCHAR))
1094 {
1095 FIXME("\n");
1096 return;
1097 }
1098
1099 /* retrieve the file system */
1100 SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFileSys);
1101 szFileSys[(sizeof(szFileSys)/sizeof(WCHAR))-1] = L'\0';
1102
1103 /* retrieve the volume label */
1104 hDlgCtrl = GetWindow(hwndDlg, 28679);
1105 Length = SendMessageW(hDlgCtrl, WM_GETTEXTLENGTH, 0, 0);
1106 if (Length + 1 > sizeof(szLabel)/sizeof(WCHAR))
1107 {
1108 FIXME("\n");
1109 return;
1110 }
1111 SendMessageW(hDlgCtrl, WM_GETTEXT, sizeof(szLabel)/sizeof(WCHAR), (LPARAM)szLabel);
1112 szLabel[(sizeof(szLabel)/sizeof(WCHAR))-1] = L'\0';
1113
1114 /* check for quickformat */
1115 if (SendDlgItemMessageW(hwndDlg, 28674, BM_GETCHECK, 0, 0) == BST_CHECKED)
1116 QuickFormat = TRUE;
1117 else
1118 QuickFormat = FALSE;
1119
1120 /* get the cluster size */
1121 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
1122 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
1123 if (iSelIndex == CB_ERR)
1124 {
1125 FIXME("\n");
1126 return;
1127 }
1128 ClusterSize = SendMessageW(hDlgCtrl, CB_GETITEMDATA, iSelIndex, 0);
1129 if (ClusterSize == CB_ERR)
1130 {
1131 FIXME("\n");
1132 return;
1133 }
1134
1135 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
1136 ShowWindow(hDlgCtrl, SW_SHOW);
1137 SendMessageW(hDlgCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
1138 bSuccess = FALSE;
1139
1140 /* FIXME
1141 * will cause display problems
1142 * when performing more than one format
1143 */
1144 FormatDrvDialog = hwndDlg;
1145
1146 pContext->FormatEx(szDrive,
1147 FMIFS_HARDDISK, /* FIXME */
1148 szFileSys,
1149 szLabel,
1150 QuickFormat,
1151 ClusterSize,
1152 FormatExCB);
1153
1154 ShowWindow(hDlgCtrl, SW_HIDE);
1155 FormatDrvDialog = NULL;
1156 if (!bSuccess)
1157 {
1158 pContext->Result = SHFMT_ERROR;
1159 }
1160 else if (QuickFormat)
1161 {
1162 pContext->Result = SHFMT_OPT_FULL;
1163 }
1164 else
1165 {
1166 pContext->Result = FALSE;
1167 }
1168 }
1169
1170
1171 BOOL
1172 CALLBACK
1173 FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1174 {
1175 PFORMAT_DRIVE_CONTEXT pContext;
1176
1177 switch(uMsg)
1178 {
1179 case WM_INITDIALOG:
1180 InitializeFormatDriveDlg(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
1181 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
1182 return TRUE;
1183 case WM_COMMAND:
1184 switch(LOWORD(wParam))
1185 {
1186 case IDOK:
1187 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1188 FormatDrive(hwndDlg, pContext);
1189 break;
1190 case IDCANCEL:
1191 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1192 EndDialog(hwndDlg, pContext->Result);
1193 break;
1194 case 28677: // filesystem combo
1195 if (HIWORD(wParam) == CBN_SELENDOK)
1196 {
1197 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
1198 InsertDefaultClusterSizeForFs(hwndDlg, pContext);
1199 }
1200 break;
1201 }
1202 }
1203 return FALSE;
1204 }
1205
1206
1207 BOOL
1208 InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext)
1209 {
1210 INITIALIZE_FMIFS InitFmifs;
1211 BOOLEAN ret;
1212 HMODULE hLibrary;
1213
1214 hLibrary = pContext->hLibrary = LoadLibraryW(L"fmifs.dll");
1215 if(!hLibrary)
1216 {
1217 ERR("failed to load fmifs.dll\n");
1218 return FALSE;
1219 }
1220
1221 InitFmifs = (INITIALIZE_FMIFS)GetProcAddress(hLibrary, "InitializeFmIfs");
1222 if (!InitFmifs)
1223 {
1224 ERR("InitializeFmIfs export is missing\n");
1225 FreeLibrary(hLibrary);
1226 return FALSE;
1227 }
1228
1229 ret = (*InitFmifs)(NULL, DLL_PROCESS_ATTACH, NULL);
1230 if (!ret)
1231 {
1232 ERR("fmifs failed to initialize\n");
1233 FreeLibrary(hLibrary);
1234 return FALSE;
1235 }
1236
1237 pContext->QueryAvailableFileSystemFormat = (QUERY_AVAILABLEFSFORMAT)GetProcAddress(hLibrary, "QueryAvailableFileSystemFormat");
1238 if (!pContext->QueryAvailableFileSystemFormat)
1239 {
1240 ERR("QueryAvailableFileSystemFormat export is missing\n");
1241 FreeLibrary(hLibrary);
1242 return FALSE;
1243 }
1244
1245 pContext->FormatEx = (FORMAT_EX) GetProcAddress(hLibrary, "FormatEx");
1246 if (!pContext->FormatEx)
1247 {
1248 ERR("FormatEx export is missing\n");
1249 FreeLibrary(hLibrary);
1250 return FALSE;
1251 }
1252
1253 pContext->EnableVolumeCompression = (ENABLEVOLUMECOMPRESSION) GetProcAddress(hLibrary, "EnableVolumeCompression");
1254 if (!pContext->FormatEx)
1255 {
1256 ERR("EnableVolumeCompression export is missing\n");
1257 FreeLibrary(hLibrary);
1258 return FALSE;
1259 }
1260
1261 pContext->Chkdsk = (CHKDSK) GetProcAddress(hLibrary, "Chkdsk");
1262 if (!pContext->Chkdsk)
1263 {
1264 ERR("Chkdsk export is missing\n");
1265 FreeLibrary(hLibrary);
1266 return FALSE;
1267 }
1268
1269 return TRUE;
1270 }
1271
1272 /*************************************************************************
1273 * SHFormatDrive (SHELL32.@)
1274 */
1275
1276 DWORD
1277 WINAPI
1278 SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options)
1279 {
1280 FORMAT_DRIVE_CONTEXT Context;
1281 int result;
1282
1283 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd, drive, fmtID, options);
1284
1285 if (!InitializeFmifsLibrary(&Context))
1286 {
1287 ERR("failed to initialize fmifs\n");
1288 return SHFMT_NOFORMAT;
1289 }
1290
1291 Context.Drive = drive;
1292 Context.Options = options;
1293
1294 result = DialogBoxParamW(shell32_hInstance, L"FORMAT_DLG", hwnd, FormatDriveDlg, (LPARAM)&Context);
1295
1296 FreeLibrary(Context.hLibrary);
1297 return result;
1298 }
1299
1300