xref: /reactos/dll/win32/shell32/dialogs/drive.cpp (revision 2aadf2eb)
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 /*
36  * TODO: In Windows the Shell doesn't know by itself if a drive is
37  * a system one or not but rather a packet message is being sent by
38  * FMIFS library code and further translated into specific packet
39  * status codes in the Shell, the packet being _FMIFS_PACKET_TYPE.
40  *
41  * With that being said, most of this code as well as FMIFS library code
42  * have to be refactored in order to comply with the way Windows works.
43  *
44  * See the enum definition for more details:
45  * https://github.com/microsoft/winfile/blob/master/src/fmifs.h#L23
46  */
47 static BOOL
IsSystemDrive(PFORMAT_DRIVE_CONTEXT pContext)48 IsSystemDrive(PFORMAT_DRIVE_CONTEXT pContext)
49 {
50     WCHAR wszDriveLetter[6], wszSystemDrv[6];
51 
52     wszDriveLetter[0] = pContext->Drive + L'A';
53     StringCchCatW(wszDriveLetter, _countof(wszDriveLetter), L":");
54 
55     if (!GetEnvironmentVariableW(L"SystemDrive", wszSystemDrv, _countof(wszSystemDrv)))
56         return FALSE;
57 
58     if (!_wcsicmp(wszDriveLetter, wszSystemDrv))
59         return TRUE;
60 
61     return FALSE;
62 }
63 
64 static BOOL
GetDefaultClusterSize(LPWSTR szFs,PDWORD pClusterSize,PULARGE_INTEGER TotalNumberOfBytes)65 GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes)
66 {
67     DWORD ClusterSize;
68 
69     if (!_wcsicmp(szFs, L"FAT16") ||
70         !_wcsicmp(szFs, L"FAT")) // REACTOS HACK
71     {
72         if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
73             ClusterSize = 2048;
74         else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
75             ClusterSize = 512;
76         else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
77             ClusterSize = 1024;
78         else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
79             ClusterSize = 2048;
80         else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
81             ClusterSize = 4096;
82         else if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
83             ClusterSize = 8192;
84         else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
85             ClusterSize = 16384;
86         else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
87             ClusterSize = 32768;
88         else if (TotalNumberOfBytes->QuadPart <= (4096LL * 1024LL * 1024LL))
89             ClusterSize = 8192;
90         else
91             return FALSE;
92     }
93     else if (!_wcsicmp(szFs, L"FAT32"))
94     {
95         if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
96             ClusterSize = 512;
97         else if (TotalNumberOfBytes->QuadPart <= (128   * 1024 * 1024))
98             ClusterSize = 1024;
99         else if (TotalNumberOfBytes->QuadPart <= (256   * 1024 * 1024))
100             ClusterSize = 2048;
101         else if (TotalNumberOfBytes->QuadPart <= (8192LL  * 1024LL * 1024LL))
102             ClusterSize = 2048;
103         else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
104             ClusterSize = 8192;
105         else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
106             ClusterSize = 16384;
107         else
108             return FALSE;
109     }
110     else if (!_wcsicmp(szFs, L"FATX"))
111     {
112         if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
113             ClusterSize = 2048;
114         else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
115             ClusterSize = 512;
116         else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
117             ClusterSize = 1024;
118         else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
119             ClusterSize = 2048;
120         else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
121             ClusterSize = 4096;
122         else if (TotalNumberOfBytes->QuadPart <= (8192LL * 1024LL * 1024LL))
123             ClusterSize = 2048;
124         else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
125             ClusterSize = 8192;
126         else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
127             ClusterSize = 16384;
128         else
129             return FALSE;
130     }
131     else if (!_wcsicmp(szFs, L"NTFS"))
132     {
133         if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
134             ClusterSize = 512;
135         else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
136             ClusterSize = 1024;
137         else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
138             ClusterSize = 2048;
139         else
140             ClusterSize = 2048;
141     }
142     else if (!_wcsicmp(szFs, L"EXT2"))
143     {
144         // auto block size calculation
145         ClusterSize = 0;
146     }
147     else if (!_wcsicmp(szFs, L"BtrFS"))
148     {
149         // auto block size calculation
150         ClusterSize = 0;
151     }
152     else
153         return FALSE;
154 
155     *pClusterSize = ClusterSize;
156     return TRUE;
157 }
158 
159 static VOID
InsertDefaultClusterSizeForFs(HWND hwndDlg,PFORMAT_DRIVE_CONTEXT pContext)160 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
161 {
162     WCHAR wszBuf[100] = {0};
163     WCHAR wszDefaultSize[100] = {0};
164     PCWSTR pwszFsSizeLimit;
165     WCHAR szDrive[] = L"C:\\";
166     INT iSelIndex;
167     ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
168     DWORD ClusterSize;
169     LRESULT lIndex;
170     HWND hDlgCtrl;
171 
172     hDlgCtrl = GetDlgItem(hwndDlg, 28677);
173     iSelIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
174     if (iSelIndex == CB_ERR)
175         return;
176 
177     if (SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)wszBuf) == CB_ERR)
178         return;
179 
180     szDrive[0] = pContext->Drive + L'A';
181 
182     if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
183         return;
184 
185     if (!_wcsicmp(wszBuf, L"FAT16") ||
186         !_wcsicmp(wszBuf, L"FAT")) // REACTOS HACK
187     {
188         pwszFsSizeLimit = L"4GB";
189     }
190     else if (!_wcsicmp(wszBuf, L"FAT32"))
191     {
192         pwszFsSizeLimit = L"32GB";
193     }
194     else if (!_wcsicmp(wszBuf, L"FATX"))
195     {
196         pwszFsSizeLimit = L"1GB/32GB";
197     }
198     else if (!_wcsicmp(wszBuf, L"NTFS"))
199     {
200         pwszFsSizeLimit = L"256TB";
201     }
202     else if (!_wcsicmp(wszBuf, L"EXT2"))
203     {
204         pwszFsSizeLimit = L"32TB";
205     }
206     else
207     {
208         pwszFsSizeLimit = L"16EB";
209     }
210 
211     if (!_wcsicmp(wszBuf, L"FAT16") ||
212         !_wcsicmp(wszBuf, L"FAT") || // REACTOS HACK
213         !_wcsicmp(wszBuf, L"FAT32") ||
214         !_wcsicmp(wszBuf, L"FATX") ||
215         !_wcsicmp(wszBuf, L"NTFS") ||
216         !_wcsicmp(wszBuf, L"EXT2") ||
217         !_wcsicmp(wszBuf, L"BtrFS"))
218     {
219         if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes))
220         {
221             TRACE("%S is not supported on drive larger than %S, current size: %lu\n", wszBuf, pwszFsSizeLimit, TotalNumberOfBytes.QuadPart);
222             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
223             return;
224         }
225 
226         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszDefaultSize, _countof(wszDefaultSize)))
227         {
228             hDlgCtrl = GetDlgItem(hwndDlg, 28680); // Get the window handle of "allocation unit size" combobox
229             SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
230             lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszDefaultSize);
231             if (lIndex != CB_ERR)
232                 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
233             SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
234         }
235 
236         if (!_wcsicmp(wszBuf, L"NTFS"))
237         {
238             ClusterSize = 512;
239             for (lIndex = 0; lIndex < 4; lIndex++)
240             {
241                 TotalNumberOfBytes.QuadPart = ClusterSize;
242                 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, wszDefaultSize, _countof(wszDefaultSize)))
243                 {
244                     lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszDefaultSize);
245                     if (lIndex != CB_ERR)
246                         SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
247                 }
248                 ClusterSize *= 2;
249             }
250         }
251 
252         SendMessageW(GetDlgItem(hwndDlg, 28675), BM_SETCHECK, BST_UNCHECKED, 0);
253         if (!_wcsicmp(wszBuf, L"EXT2") ||
254             !_wcsicmp(wszBuf, L"BtrFS") ||
255             !_wcsicmp(wszBuf, L"NTFS"))
256         {
257             /* Enable the "Enable Compression" button */
258             EnableWindow(GetDlgItem(hwndDlg, 28675), TRUE);
259         }
260         else
261         {
262             /* Disable the "Enable Compression" button */
263             EnableWindow(GetDlgItem(hwndDlg, 28675), FALSE);
264         }
265     }
266     else
267     {
268         FIXME("Unknown filesystem: %ls\n", wszBuf);
269         SendDlgItemMessageW(hwndDlg, 28680, CB_RESETCONTENT, iSelIndex, 0);
270         return;
271     }
272 }
273 
274 static VOID
InitializeFormatDriveDlg(HWND hwndDlg,PFORMAT_DRIVE_CONTEXT pContext)275 InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
276 {
277     WCHAR szText[120];
278     WCHAR szDrive[] = L"C:\\";
279     WCHAR szFs[30] = L"";
280     INT cchText;
281     ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
282     DWORD dwIndex, dwDefault;
283     UCHAR uMinor, uMajor;
284     BOOLEAN Latest;
285     HWND hwndFileSystems;
286 
287     cchText = GetWindowTextW(hwndDlg, szText, _countof(szText) - 1);
288     if (cchText < 0)
289         cchText = 0;
290     szText[cchText++] = L' ';
291     szDrive[0] = pContext->Drive + L'A';
292     if (GetVolumeInformationW(szDrive, &szText[cchText], _countof(szText) - cchText, NULL, NULL, NULL, szFs, _countof(szFs)))
293     {
294         if (szText[cchText] == UNICODE_NULL)
295         {
296             /* load default volume label */
297             cchText += LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[cchText], _countof(szText) - cchText);
298         }
299         else
300         {
301             /* set volume label */
302             SetDlgItemTextW(hwndDlg, 28679, &szText[cchText]);
303             cchText += wcslen(&szText[cchText]);
304         }
305     }
306 
307     StringCchPrintfW(szText + cchText, _countof(szText) - cchText, L" (%c:)", szDrive[0]);
308 
309     /* set window text */
310     SetWindowTextW(hwndDlg, szText);
311 
312     if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
313     {
314         if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szText, _countof(szText)))
315         {
316             /* add drive capacity */
317             SendDlgItemMessageW(hwndDlg, 28673, CB_ADDSTRING, 0, (LPARAM)szText);
318             SendDlgItemMessageW(hwndDlg, 28673, CB_SETCURSEL, 0, (LPARAM)0);
319         }
320     }
321 
322     if (pContext->Options & SHFMT_OPT_FULL)
323     {
324         /* check quick format button */
325         SendDlgItemMessageW(hwndDlg, 28674, BM_SETCHECK, BST_CHECKED, 0);
326     }
327 
328     /* enumerate all available filesystems */
329     dwIndex = 0;
330     dwDefault = 0;
331     hwndFileSystems = GetDlgItem(hwndDlg, 28677);
332 
333     while(QueryAvailableFileSystemFormat(dwIndex, szText, &uMajor, &uMinor, &Latest))
334     {
335         if (!_wcsicmp(szText, szFs))
336             dwDefault = dwIndex;
337 
338         SendMessageW(hwndFileSystems, CB_ADDSTRING, 0, (LPARAM)szText);
339         dwIndex++;
340     }
341 
342     if (!dwIndex)
343     {
344         ERR("no filesystem providers\n");
345         return;
346     }
347 
348     /* select default filesys */
349     SendMessageW(hwndFileSystems, CB_SETCURSEL, dwDefault, 0);
350     /* setup cluster combo */
351     InsertDefaultClusterSizeForFs(hwndDlg, pContext);
352 }
353 
354 static HWND FormatDrvDialog = NULL;
355 static BOOLEAN bSuccess = FALSE;
356 
357 static BOOLEAN NTAPI
FormatExCB(IN CALLBACKCOMMAND Command,IN ULONG SubAction,IN PVOID ActionInfo)358 FormatExCB(
359     IN CALLBACKCOMMAND Command,
360     IN ULONG SubAction,
361     IN PVOID ActionInfo)
362 {
363     PDWORD Progress;
364     PBOOLEAN pSuccess;
365     switch(Command)
366     {
367         case PROGRESS:
368             Progress = (PDWORD)ActionInfo;
369             SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, (WPARAM)*Progress, 0);
370             break;
371         case DONE:
372             pSuccess = (PBOOLEAN)ActionInfo;
373             bSuccess = (*pSuccess);
374             ShellMessageBoxW(shell32_hInstance, FormatDrvDialog, MAKEINTRESOURCEW(IDS_FORMAT_COMPLETE), MAKEINTRESOURCEW(IDS_FORMAT_TITLE), MB_OK | MB_ICONINFORMATION);
375             SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, 0, 0);
376             break;
377 
378         case VOLUMEINUSE:
379         case INSUFFICIENTRIGHTS:
380         case FSNOTSUPPORTED:
381         case CLUSTERSIZETOOSMALL:
382             bSuccess = FALSE;
383             FIXME("Unsupported command in FormatExCB\n");
384             break;
385 
386         default:
387             break;
388     }
389 
390     return TRUE;
391 }
392 
393 VOID
FormatDrive(HWND hwndDlg,PFORMAT_DRIVE_CONTEXT pContext)394 FormatDrive(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
395 {
396     WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
397     WCHAR szFileSys[40] = {0};
398     WCHAR szLabel[40] = {0};
399     INT iSelIndex;
400     UINT Length;
401     HWND hDlgCtrl;
402     BOOL QuickFormat;
403     DWORD ClusterSize;
404     DWORD DriveType;
405     FMIFS_MEDIA_FLAG MediaFlag = FMIFS_HARDDISK;
406 
407     /* set volume path */
408     szDrive[0] = pContext->Drive + L'A';
409 
410     /* get filesystem */
411     hDlgCtrl = GetDlgItem(hwndDlg, 28677);
412     iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
413     if (iSelIndex == CB_ERR)
414     {
415         ERR("Unable to get file system selection\n");
416         return;
417     }
418     Length = SendMessageW(hDlgCtrl, CB_GETLBTEXTLEN, iSelIndex, 0);
419     if ((int)Length == CB_ERR || Length + 1 > _countof(szFileSys))
420     {
421         ERR("Unable to get file system selection\n");
422         return;
423     }
424 
425     /* retrieve the file system */
426     SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFileSys);
427     szFileSys[_countof(szFileSys)-1] = L'\0';
428 
429     /* retrieve the volume label */
430     hDlgCtrl = GetWindow(hwndDlg, 28679);
431     Length = SendMessageW(hDlgCtrl, WM_GETTEXTLENGTH, 0, 0);
432     if (Length + 1 > _countof(szLabel))
433     {
434         ERR("Unable to get volume label\n");
435         return;
436     }
437     SendMessageW(hDlgCtrl, WM_GETTEXT, _countof(szLabel), (LPARAM)szLabel);
438     szLabel[(sizeof(szLabel)/sizeof(WCHAR))-1] = L'\0';
439 
440     /* check for quickformat */
441     if (SendDlgItemMessageW(hwndDlg, 28674, BM_GETCHECK, 0, 0) == BST_CHECKED)
442         QuickFormat = TRUE;
443     else
444         QuickFormat = FALSE;
445 
446     /* get the cluster size */
447     hDlgCtrl = GetDlgItem(hwndDlg, 28680);
448     iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
449     if (iSelIndex == CB_ERR)
450     {
451         FIXME("\n");
452         return;
453     }
454     ClusterSize = SendMessageW(hDlgCtrl, CB_GETITEMDATA, iSelIndex, 0);
455     if ((int)ClusterSize == CB_ERR)
456     {
457         FIXME("\n");
458         return;
459     }
460 
461     hDlgCtrl = GetDlgItem(hwndDlg, 28680);
462     SendMessageW(hDlgCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
463     bSuccess = FALSE;
464 
465     /* FIXME
466      * will cause display problems
467      * when performing more than one format
468      */
469     FormatDrvDialog = hwndDlg;
470 
471     /* See if the drive is removable or not */
472     DriveType = GetDriveTypeW(szDrive);
473     switch (DriveType)
474     {
475         case DRIVE_UNKNOWN:
476         case DRIVE_REMOTE:
477         case DRIVE_CDROM:
478         case DRIVE_NO_ROOT_DIR:
479         {
480             FIXME("\n");
481             return;
482         }
483 
484         case DRIVE_REMOVABLE:
485             MediaFlag = FMIFS_FLOPPY;
486             break;
487 
488         case DRIVE_FIXED:
489         case DRIVE_RAMDISK:
490             MediaFlag = FMIFS_HARDDISK;
491             break;
492     }
493 
494     /* Format the drive */
495     FormatEx(szDrive,
496              MediaFlag,
497              szFileSys,
498              szLabel,
499              QuickFormat,
500              ClusterSize,
501              FormatExCB);
502 
503     FormatDrvDialog = NULL;
504     if (!bSuccess)
505     {
506         pContext->Result = SHFMT_ERROR;
507     }
508     else if (QuickFormat)
509     {
510         pContext->Result = SHFMT_OPT_FULL;
511     }
512     else
513     {
514         pContext->Result = FALSE;
515     }
516 }
517 
518 struct FORMAT_DRIVE_PARAMS
519 {
520     HWND hwndDlg;
521     PFORMAT_DRIVE_CONTEXT pContext;
522 };
523 
DoFormatDrive(void * args)524 static unsigned __stdcall DoFormatDrive(void *args)
525 {
526     FORMAT_DRIVE_PARAMS *pParams = reinterpret_cast<FORMAT_DRIVE_PARAMS *>(args);
527     HWND hwndDlg = pParams->hwndDlg;
528     PFORMAT_DRIVE_CONTEXT pContext = pParams->pContext;
529 
530 	/* Disable controls during format */
531     HMENU hSysMenu = GetSystemMenu(hwndDlg, FALSE);
532     EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
533     EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
534     EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
535     EnableWindow(GetDlgItem(hwndDlg, 28673), FALSE);
536     EnableWindow(GetDlgItem(hwndDlg, 28677), FALSE);
537     EnableWindow(GetDlgItem(hwndDlg, 28680), FALSE);
538     EnableWindow(GetDlgItem(hwndDlg, 28679), FALSE);
539     EnableWindow(GetDlgItem(hwndDlg, 28674), FALSE);
540 
541     FormatDrive(hwndDlg, pContext);
542 
543 	/* Re-enable controls after format */
544     EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);
545     EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), TRUE);
546     EnableWindow(GetDlgItem(hwndDlg, 28673), TRUE);
547     EnableWindow(GetDlgItem(hwndDlg, 28677), TRUE);
548     EnableWindow(GetDlgItem(hwndDlg, 28680), TRUE);
549     EnableWindow(GetDlgItem(hwndDlg, 28679), TRUE);
550     EnableWindow(GetDlgItem(hwndDlg, 28674), TRUE);
551     EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
552     pContext->bFormattingNow = FALSE;
553 
554     delete pParams;
555     return 0;
556 }
557 
558 static INT_PTR CALLBACK
FormatDriveDlg(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)559 FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
560 {
561     PFORMAT_DRIVE_CONTEXT pContext;
562 
563     switch(uMsg)
564     {
565         case WM_INITDIALOG:
566             InitializeFormatDriveDlg(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
567             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
568             return TRUE;
569         case WM_COMMAND:
570             switch(LOWORD(wParam))
571             {
572                 case IDOK:
573                     pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
574                     if (pContext->bFormattingNow)
575                         break;
576 
577                     if (ShellMessageBoxW(shell32_hInstance, hwndDlg,
578                                          MAKEINTRESOURCEW(IDS_FORMAT_WARNING),
579                                          MAKEINTRESOURCEW(IDS_FORMAT_TITLE),
580                                          MB_OKCANCEL | MB_ICONWARNING) == IDOK)
581                     {
582                         pContext->bFormattingNow = TRUE;
583 
584                         FORMAT_DRIVE_PARAMS *pParams = new FORMAT_DRIVE_PARAMS;
585                         pParams->hwndDlg = hwndDlg;
586                         pParams->pContext = pContext;
587 
588                         unsigned tid;
589                         HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, DoFormatDrive, pParams, 0, &tid);
590                         CloseHandle(hThread);
591                     }
592                     break;
593                 case IDCANCEL:
594                     pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
595                     if (pContext->bFormattingNow)
596                         break;
597 
598                     EndDialog(hwndDlg, pContext->Result);
599                     break;
600                 case 28677: // filesystem combo
601                     if (HIWORD(wParam) == CBN_SELENDOK)
602                     {
603                         pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
604                         if (pContext->bFormattingNow)
605                             break;
606 
607                         InsertDefaultClusterSizeForFs(hwndDlg, pContext);
608                     }
609                     break;
610             }
611     }
612     return FALSE;
613 }
614 
615 /*************************************************************************
616  *              SHFormatDrive (SHELL32.@)
617  */
618 
619 DWORD
620 WINAPI
SHFormatDrive(HWND hwnd,UINT drive,UINT fmtID,UINT options)621 SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options)
622 {
623     FORMAT_DRIVE_CONTEXT Context;
624     int result;
625 
626     TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd, drive, fmtID, options);
627 
628     Context.Drive = drive;
629     Context.Options = options;
630     Context.Result = FALSE;
631     Context.bFormattingNow = FALSE;
632 
633     if (!IsSystemDrive(&Context))
634     {
635         result = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_FORMAT_DRIVE), hwnd, FormatDriveDlg, (LPARAM)&Context);
636     }
637     else
638     {
639         result = SHFMT_ERROR;
640         ShellMessageBoxW(shell32_hInstance, hwnd, MAKEINTRESOURCEW(IDS_NO_FORMAT), MAKEINTRESOURCEW(IDS_NO_FORMAT_TITLE), MB_OK | MB_ICONWARNING);
641         TRACE("SHFormatDrive(): The provided drive for format is a system volume! Aborting...\n");
642     }
643 
644     return result;
645 }
646