[CALC] Fix input bug when display is in error. (#5988)
[reactos.git] / dll / win32 / shell32 / dialogs / drive.cpp
1 /*
2 * Shell Library Functions
3 *
4 * Copyright 2005 Johannes Anderwald
5 * Copyright 2017 Katayama Hirofumi MZ
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "precomp.h"
23 #include <process.h>
24
25 WINE_DEFAULT_DEBUG_CHANNEL(shell);
26
27 typedef struct
28 {
29 WCHAR Drive;
30 UINT Options;
31 UINT Result;
32 BOOL bFormattingNow;
33 } FORMAT_DRIVE_CONTEXT, *PFORMAT_DRIVE_CONTEXT;
34
35 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
36 HPROPSHEETPAGE SH_CreatePropertySheetPage(LPCSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle);
37
38 /*
39 * TODO: In Windows the Shell doesn't know by itself if a drive is
40 * a system one or not but rather a packet message is being sent by
41 * FMIFS library code and further translated into specific packet
42 * status codes in the Shell, the packet being _FMIFS_PACKET_TYPE.
43 *
44 * With that being said, most of this code as well as FMIFS library code
45 * have to be refactored in order to comply with the way Windows works.
46 *
47 * See the enum definition for more details:
48 * https://github.com/microsoft/winfile/blob/master/src/fmifs.h#L23
49 */
50 static BOOL
51 IsSystemDrive(PFORMAT_DRIVE_CONTEXT pContext)
52 {
53 WCHAR wszDriveLetter[6], wszSystemDrv[6];
54
55 wszDriveLetter[0] = pContext->Drive + L'A';
56 StringCchCatW(wszDriveLetter, _countof(wszDriveLetter), L":");
57
58 if (!GetEnvironmentVariableW(L"SystemDrive", wszSystemDrv, _countof(wszSystemDrv)))
59 return FALSE;
60
61 if (!wcsicmp(wszDriveLetter, wszSystemDrv))
62 return TRUE;
63
64 return FALSE;
65 }
66
67 static BOOL
68 GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes)
69 {
70 DWORD ClusterSize;
71
72 if (!wcsicmp(szFs, L"FAT16") ||
73 !wcsicmp(szFs, L"FAT")) // REACTOS HACK
74 {
75 if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
76 ClusterSize = 2048;
77 else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
78 ClusterSize = 512;
79 else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
80 ClusterSize = 1024;
81 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
82 ClusterSize = 2048;
83 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
84 ClusterSize = 4096;
85 else if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
86 ClusterSize = 8192;
87 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
88 ClusterSize = 16384;
89 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
90 ClusterSize = 32768;
91 else if (TotalNumberOfBytes->QuadPart <= (4096LL * 1024LL * 1024LL))
92 ClusterSize = 8192;
93 else
94 return FALSE;
95 }
96 else if (!wcsicmp(szFs, L"FAT32"))
97 {
98 if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
99 ClusterSize = 512;
100 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
101 ClusterSize = 1024;
102 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
103 ClusterSize = 2048;
104 else if (TotalNumberOfBytes->QuadPart <= (8192LL * 1024LL * 1024LL))
105 ClusterSize = 2048;
106 else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
107 ClusterSize = 8192;
108 else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
109 ClusterSize = 16384;
110 else
111 return FALSE;
112 }
113 else if (!wcsicmp(szFs, L"FATX"))
114 {
115 if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
116 ClusterSize = 2048;
117 else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
118 ClusterSize = 512;
119 else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
120 ClusterSize = 1024;
121 else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
122 ClusterSize = 2048;
123 else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
124 ClusterSize = 4096;
125 else if (TotalNumberOfBytes->QuadPart <= (8192LL * 1024LL * 1024LL))
126 ClusterSize = 2048;
127 else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
128 ClusterSize = 8192;
129 else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
130 ClusterSize = 16384;
131 else
132 return FALSE;
133 }
134 else if (!wcsicmp(szFs, L"NTFS"))
135 {
136 if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
137 ClusterSize = 512;
138 else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
139 ClusterSize = 1024;
140 else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
141 ClusterSize = 2048;
142 else
143 ClusterSize = 2048;
144 }
145 else if (!wcsicmp(szFs, L"EXT2"))
146 {
147 // auto block size calculation
148 ClusterSize = 0;
149 }
150 else if (!wcsicmp(szFs, L"BtrFS"))
151 {
152 // auto block size calculation
153 ClusterSize = 0;
154 }
155 else
156 return FALSE;
157
158 *pClusterSize = ClusterSize;
159 return TRUE;
160 }
161
162 typedef struct _DRIVE_PROP_PAGE
163 {
164 LPCSTR resname;
165 DLGPROC dlgproc;
166 UINT DriveType;
167 } DRIVE_PROP_PAGE;
168
169 HRESULT
170 SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
171 {
172 HPSXA hpsx = NULL;
173 HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
174 PROPSHEETHEADERW psh;
175 CComObject<CDrvDefExt> *pDrvDefExt = NULL;
176 WCHAR wszName[256];
177
178 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
179 psh.dwSize = sizeof(PROPSHEETHEADERW);
180 psh.dwFlags = 0; // FIXME: make it modeless
181 psh.hwndParent = NULL;
182 psh.nStartPage = 0;
183 psh.phpage = hpsp;
184
185 LPITEMIDLIST completePidl = ILCombine(pidlFolder, apidl[0]);
186 if (!completePidl)
187 return E_OUTOFMEMORY;
188
189 if (ILGetDisplayNameExW(NULL, completePidl, wszName, ILGDN_NORMAL))
190 {
191 psh.pszCaption = wszName;
192 psh.dwFlags |= PSH_PROPTITLE;
193 }
194
195 ILFree(completePidl);
196
197 CComPtr<IDataObject> pDataObj;
198 HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
199
200 if (SUCCEEDED(hr))
201 {
202 hr = CComObject<CDrvDefExt>::CreateInstance(&pDrvDefExt);
203 if (SUCCEEDED(hr))
204 {
205 pDrvDefExt->AddRef(); // CreateInstance returns object with 0 ref count
206 hr = pDrvDefExt->Initialize(pidlFolder, pDataObj, NULL);
207 if (SUCCEEDED(hr))
208 {
209 hr = pDrvDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&psh);
210 if (FAILED(hr))
211 ERR("AddPages failed\n");
212 } else
213 ERR("Initialize failed\n");
214 }
215
216 hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", MAX_PROPERTY_SHEET_PAGE, pDataObj);
217 if (hpsx)
218 SHAddFromPropSheetExtArray(hpsx, (LPFNADDPROPSHEETPAGE)AddPropSheetPageCallback, (LPARAM)&psh);
219 }
220
221 // NOTE: Currently property sheet is modal. If we make it modeless, then it returns HWND.
222 INT_PTR ret = PropertySheetW(&psh);
223
224 if (hpsx)
225 SHDestroyPropSheetExtArray(hpsx);
226 if (pDrvDefExt)
227 pDrvDefExt->Release();
228
229 if (ret > 0)
230 return S_OK;
231 if (ret == 0)
232 return S_FALSE;
233 return E_FAIL;
234 }
235
236 static VOID
237 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
238 {
239 WCHAR wszBuf[100] = {0};
240 WCHAR wszDefaultSize[100] = {0};
241 PCWSTR pwszFsSizeLimit;
242 WCHAR szDrive[] = L"C:\\";
243 INT iSelIndex;
244 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
245 DWORD ClusterSize;
246 LRESULT lIndex;
247 HWND hDlgCtrl;
248
249 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
250 iSelIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
251 if (iSelIndex == CB_ERR)
252 return;
253
254 if (SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)wszBuf) == CB_ERR)
255 return;
256
257 szDrive[0] = pContext->Drive + L'A';
258
259 if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
260 return;
261
262 if (!wcsicmp(wszBuf, L"FAT16") ||
263 !wcsicmp(wszBuf, L"FAT")) // REACTOS HACK
264 {
265 pwszFsSizeLimit = L"4GB";
266 }
267 else if (!wcsicmp(wszBuf, L"FAT32"))
268 {
269 pwszFsSizeLimit = L"32GB";
270 }
271 else if (!wcsicmp(wszBuf, L"FATX"))
272 {
273 pwszFsSizeLimit = L"1GB/32GB";
274 }
275 else if (!wcsicmp(wszBuf, L"NTFS"))
276 {
277 pwszFsSizeLimit = L"256TB";
278 }
279 else if (!wcsicmp(wszBuf, L"EXT2"))
280 {
281 pwszFsSizeLimit = L"32TB";
282 }
283 else
284 {
285 pwszFsSizeLimit = L"16EB";
286 }
287
288 if (!wcsicmp(wszBuf, L"FAT16") ||
289 !wcsicmp(wszBuf, L"FAT") || // REACTOS HACK
290 !wcsicmp(wszBuf, L"FAT32") ||
291 !wcsicmp(wszBuf, L"FATX") ||
292 !wcsicmp(wszBuf, L"NTFS") ||
293 !wcsicmp(wszBuf, L"EXT2") ||
294 !wcsicmp(wszBuf, L"BtrFS"))
295 {
296 if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes))
297 {
298 TRACE("%S is not supported on drive larger than %S, current size: %lu\n", wszBuf, pwszFsSizeLimit, TotalNumberOfBytes.QuadPart);
299 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
300 return;
301 }
302
303 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszDefaultSize, _countof(wszDefaultSize)))
304 {
305 hDlgCtrl = GetDlgItem(hwndDlg, 28680); // Get the window handle of "allocation unit size" combobox
306 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
307 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszDefaultSize);
308 if (lIndex != CB_ERR)
309 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
310 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
311 }
312
313 if (!wcsicmp(wszBuf, L"NTFS"))
314 {
315 ClusterSize = 512;
316 for (lIndex = 0; lIndex < 4; lIndex++)
317 {
318 TotalNumberOfBytes.QuadPart = ClusterSize;
319 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, wszDefaultSize, _countof(wszDefaultSize)))
320 {
321 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszDefaultSize);
322 if (lIndex != CB_ERR)
323 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
324 }
325 ClusterSize *= 2;
326 }
327 }
328
329 SendMessageW(GetDlgItem(hwndDlg, 28675), BM_SETCHECK, BST_UNCHECKED, 0);
330 if (!wcsicmp(wszBuf, L"EXT2") ||
331 !wcsicmp(wszBuf, L"BtrFS") ||
332 !wcsicmp(wszBuf, L"NTFS"))
333 {
334 /* Enable the "Enable Compression" button */
335 EnableWindow(GetDlgItem(hwndDlg, 28675), TRUE);
336 }
337 else
338 {
339 /* Disable the "Enable Compression" button */
340 EnableWindow(GetDlgItem(hwndDlg, 28675), FALSE);
341 }
342 }
343 else
344 {
345 FIXME("Unknown filesystem: %ls\n", wszBuf);
346 SendDlgItemMessageW(hwndDlg, 28680, CB_RESETCONTENT, iSelIndex, 0);
347 return;
348 }
349 }
350
351 static VOID
352 InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
353 {
354 WCHAR szText[120];
355 WCHAR szDrive[] = L"C:\\";
356 WCHAR szFs[30] = L"";
357 INT cchText;
358 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
359 DWORD dwIndex, dwDefault;
360 UCHAR uMinor, uMajor;
361 BOOLEAN Latest;
362 HWND hwndFileSystems;
363
364 cchText = GetWindowTextW(hwndDlg, szText, _countof(szText) - 1);
365 if (cchText < 0)
366 cchText = 0;
367 szText[cchText++] = L' ';
368 szDrive[0] = pContext->Drive + L'A';
369 if (GetVolumeInformationW(szDrive, &szText[cchText], _countof(szText) - cchText, NULL, NULL, NULL, szFs, _countof(szFs)))
370 {
371 if (szText[cchText] == UNICODE_NULL)
372 {
373 /* load default volume label */
374 cchText += LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[cchText], _countof(szText) - cchText);
375 }
376 else
377 {
378 /* set volume label */
379 SetDlgItemTextW(hwndDlg, 28679, &szText[cchText]);
380 cchText += wcslen(&szText[cchText]);
381 }
382 }
383
384 StringCchPrintfW(szText + cchText, _countof(szText) - cchText, L" (%c:)", szDrive[0]);
385
386 /* set window text */
387 SetWindowTextW(hwndDlg, szText);
388
389 if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
390 {
391 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szText, _countof(szText)))
392 {
393 /* add drive capacity */
394 SendDlgItemMessageW(hwndDlg, 28673, CB_ADDSTRING, 0, (LPARAM)szText);
395 SendDlgItemMessageW(hwndDlg, 28673, CB_SETCURSEL, 0, (LPARAM)0);
396 }
397 }
398
399 if (pContext->Options & SHFMT_OPT_FULL)
400 {
401 /* check quick format button */
402 SendDlgItemMessageW(hwndDlg, 28674, BM_SETCHECK, BST_CHECKED, 0);
403 }
404
405 /* enumerate all available filesystems */
406 dwIndex = 0;
407 dwDefault = 0;
408 hwndFileSystems = GetDlgItem(hwndDlg, 28677);
409
410 while(QueryAvailableFileSystemFormat(dwIndex, szText, &uMajor, &uMinor, &Latest))
411 {
412 if (!wcsicmp(szText, szFs))
413 dwDefault = dwIndex;
414
415 SendMessageW(hwndFileSystems, CB_ADDSTRING, 0, (LPARAM)szText);
416 dwIndex++;
417 }
418
419 if (!dwIndex)
420 {
421 ERR("no filesystem providers\n");
422 return;
423 }
424
425 /* select default filesys */
426 SendMessageW(hwndFileSystems, CB_SETCURSEL, dwDefault, 0);
427 /* setup cluster combo */
428 InsertDefaultClusterSizeForFs(hwndDlg, pContext);
429 }
430
431 static HWND FormatDrvDialog = NULL;
432 static BOOLEAN bSuccess = FALSE;
433
434 static BOOLEAN NTAPI
435 FormatExCB(
436 IN CALLBACKCOMMAND Command,
437 IN ULONG SubAction,
438 IN PVOID ActionInfo)
439 {
440 PDWORD Progress;
441 PBOOLEAN pSuccess;
442 switch(Command)
443 {
444 case PROGRESS:
445 Progress = (PDWORD)ActionInfo;
446 SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, (WPARAM)*Progress, 0);
447 break;
448 case DONE:
449 pSuccess = (PBOOLEAN)ActionInfo;
450 bSuccess = (*pSuccess);
451 ShellMessageBoxW(shell32_hInstance, FormatDrvDialog, MAKEINTRESOURCEW(IDS_FORMAT_COMPLETE), MAKEINTRESOURCEW(IDS_FORMAT_TITLE), MB_OK | MB_ICONINFORMATION);
452 SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, 0, 0);
453 break;
454
455 case VOLUMEINUSE:
456 case INSUFFICIENTRIGHTS:
457 case FSNOTSUPPORTED:
458 case CLUSTERSIZETOOSMALL:
459 bSuccess = FALSE;
460 FIXME("Unsupported command in FormatExCB\n");
461 break;
462
463 default:
464 break;
465 }
466
467 return TRUE;
468 }
469
470 VOID
471 FormatDrive(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
472 {
473 WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
474 WCHAR szFileSys[40] = {0};
475 WCHAR szLabel[40] = {0};
476 INT iSelIndex;
477 UINT Length;
478 HWND hDlgCtrl;
479 BOOL QuickFormat;
480 DWORD ClusterSize;
481 DWORD DriveType;
482 FMIFS_MEDIA_FLAG MediaFlag = FMIFS_HARDDISK;
483
484 /* set volume path */
485 szDrive[0] = pContext->Drive + L'A';
486
487 /* get filesystem */
488 hDlgCtrl = GetDlgItem(hwndDlg, 28677);
489 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
490 if (iSelIndex == CB_ERR)
491 {
492 ERR("Unable to get file system selection\n");
493 return;
494 }
495 Length = SendMessageW(hDlgCtrl, CB_GETLBTEXTLEN, iSelIndex, 0);
496 if ((int)Length == CB_ERR || Length + 1 > _countof(szFileSys))
497 {
498 ERR("Unable to get file system selection\n");
499 return;
500 }
501
502 /* retrieve the file system */
503 SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFileSys);
504 szFileSys[_countof(szFileSys)-1] = L'\0';
505
506 /* retrieve the volume label */
507 hDlgCtrl = GetWindow(hwndDlg, 28679);
508 Length = SendMessageW(hDlgCtrl, WM_GETTEXTLENGTH, 0, 0);
509 if (Length + 1 > _countof(szLabel))
510 {
511 ERR("Unable to get volume label\n");
512 return;
513 }
514 SendMessageW(hDlgCtrl, WM_GETTEXT, _countof(szLabel), (LPARAM)szLabel);
515 szLabel[(sizeof(szLabel)/sizeof(WCHAR))-1] = L'\0';
516
517 /* check for quickformat */
518 if (SendDlgItemMessageW(hwndDlg, 28674, BM_GETCHECK, 0, 0) == BST_CHECKED)
519 QuickFormat = TRUE;
520 else
521 QuickFormat = FALSE;
522
523 /* get the cluster size */
524 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
525 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
526 if (iSelIndex == CB_ERR)
527 {
528 FIXME("\n");
529 return;
530 }
531 ClusterSize = SendMessageW(hDlgCtrl, CB_GETITEMDATA, iSelIndex, 0);
532 if ((int)ClusterSize == CB_ERR)
533 {
534 FIXME("\n");
535 return;
536 }
537
538 hDlgCtrl = GetDlgItem(hwndDlg, 28680);
539 SendMessageW(hDlgCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
540 bSuccess = FALSE;
541
542 /* FIXME
543 * will cause display problems
544 * when performing more than one format
545 */
546 FormatDrvDialog = hwndDlg;
547
548 /* See if the drive is removable or not */
549 DriveType = GetDriveTypeW(szDrive);
550 switch (DriveType)
551 {
552 case DRIVE_UNKNOWN:
553 case DRIVE_REMOTE:
554 case DRIVE_CDROM:
555 case DRIVE_NO_ROOT_DIR:
556 {
557 FIXME("\n");
558 return;
559 }
560
561 case DRIVE_REMOVABLE:
562 MediaFlag = FMIFS_FLOPPY;
563 break;
564
565 case DRIVE_FIXED:
566 case DRIVE_RAMDISK:
567 MediaFlag = FMIFS_HARDDISK;
568 break;
569 }
570
571 /* Format the drive */
572 FormatEx(szDrive,
573 MediaFlag,
574 szFileSys,
575 szLabel,
576 QuickFormat,
577 ClusterSize,
578 FormatExCB);
579
580 FormatDrvDialog = NULL;
581 if (!bSuccess)
582 {
583 pContext->Result = SHFMT_ERROR;
584 }
585 else if (QuickFormat)
586 {
587 pContext->Result = SHFMT_OPT_FULL;
588 }
589 else
590 {
591 pContext->Result = FALSE;
592 }
593 }
594
595 struct FORMAT_DRIVE_PARAMS
596 {
597 HWND hwndDlg;
598 PFORMAT_DRIVE_CONTEXT pContext;
599 };
600
601 static unsigned __stdcall DoFormatDrive(void *args)
602 {
603 FORMAT_DRIVE_PARAMS *pParams = reinterpret_cast<FORMAT_DRIVE_PARAMS *>(args);
604 HWND hwndDlg = pParams->hwndDlg;
605 PFORMAT_DRIVE_CONTEXT pContext = pParams->pContext;
606
607 /* Disable controls during format */
608 HMENU hSysMenu = GetSystemMenu(hwndDlg, FALSE);
609 EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
610 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
611 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
612 EnableWindow(GetDlgItem(hwndDlg, 28673), FALSE);
613 EnableWindow(GetDlgItem(hwndDlg, 28677), FALSE);
614 EnableWindow(GetDlgItem(hwndDlg, 28680), FALSE);
615 EnableWindow(GetDlgItem(hwndDlg, 28679), FALSE);
616 EnableWindow(GetDlgItem(hwndDlg, 28674), FALSE);
617
618 FormatDrive(hwndDlg, pContext);
619
620 /* Re-enable controls after format */
621 EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);
622 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), TRUE);
623 EnableWindow(GetDlgItem(hwndDlg, 28673), TRUE);
624 EnableWindow(GetDlgItem(hwndDlg, 28677), TRUE);
625 EnableWindow(GetDlgItem(hwndDlg, 28680), TRUE);
626 EnableWindow(GetDlgItem(hwndDlg, 28679), TRUE);
627 EnableWindow(GetDlgItem(hwndDlg, 28674), TRUE);
628 EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
629 pContext->bFormattingNow = FALSE;
630
631 delete pParams;
632 return 0;
633 }
634
635 static INT_PTR CALLBACK
636 FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
637 {
638 PFORMAT_DRIVE_CONTEXT pContext;
639
640 switch(uMsg)
641 {
642 case WM_INITDIALOG:
643 InitializeFormatDriveDlg(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
644 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
645 return TRUE;
646 case WM_COMMAND:
647 switch(LOWORD(wParam))
648 {
649 case IDOK:
650 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
651 if (pContext->bFormattingNow)
652 break;
653
654 if (ShellMessageBoxW(shell32_hInstance, hwndDlg,
655 MAKEINTRESOURCEW(IDS_FORMAT_WARNING),
656 MAKEINTRESOURCEW(IDS_FORMAT_TITLE),
657 MB_OKCANCEL | MB_ICONWARNING) == IDOK)
658 {
659 pContext->bFormattingNow = TRUE;
660
661 FORMAT_DRIVE_PARAMS *pParams = new FORMAT_DRIVE_PARAMS;
662 pParams->hwndDlg = hwndDlg;
663 pParams->pContext = pContext;
664
665 unsigned tid;
666 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, DoFormatDrive, pParams, 0, &tid);
667 CloseHandle(hThread);
668 }
669 break;
670 case IDCANCEL:
671 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
672 if (pContext->bFormattingNow)
673 break;
674
675 EndDialog(hwndDlg, pContext->Result);
676 break;
677 case 28677: // filesystem combo
678 if (HIWORD(wParam) == CBN_SELENDOK)
679 {
680 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
681 if (pContext->bFormattingNow)
682 break;
683
684 InsertDefaultClusterSizeForFs(hwndDlg, pContext);
685 }
686 break;
687 }
688 }
689 return FALSE;
690 }
691
692 /*************************************************************************
693 * SHFormatDrive (SHELL32.@)
694 */
695
696 DWORD
697 WINAPI
698 SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options)
699 {
700 FORMAT_DRIVE_CONTEXT Context;
701 int result;
702
703 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd, drive, fmtID, options);
704
705 Context.Drive = drive;
706 Context.Options = options;
707 Context.Result = FALSE;
708 Context.bFormattingNow = FALSE;
709
710 if (!IsSystemDrive(&Context))
711 {
712 result = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_FORMAT_DRIVE), hwnd, FormatDriveDlg, (LPARAM)&Context);
713 }
714 else
715 {
716 result = SHFMT_ERROR;
717 ShellMessageBoxW(shell32_hInstance, hwnd, MAKEINTRESOURCEW(IDS_NO_FORMAT), MAKEINTRESOURCEW(IDS_NO_FORMAT_TITLE), MB_OK | MB_ICONWARNING);
718 TRACE("SHFormatDrive(): The provided drive for format is a system volume! Aborting...\n");
719 }
720
721 return result;
722 }