xref: /reactos/dll/win32/shell32/dialogs/drive.cpp (revision 50cf16b3)
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 
24 WINE_DEFAULT_DEBUG_CHANNEL(shell);
25 
26 typedef struct
27 {
28     WCHAR   Drive;
29     UINT    Options;
30     UINT Result;
31 } FORMAT_DRIVE_CONTEXT, *PFORMAT_DRIVE_CONTEXT;
32 
33 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
34 HPROPSHEETPAGE SH_CreatePropertySheetPage(LPCSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle);
35 
36 static BOOL
37 GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes)
38 {
39     DWORD ClusterSize;
40 
41     if (!wcsicmp(szFs, L"FAT16") ||
42         !wcsicmp(szFs, L"FAT")) //REACTOS HACK
43     {
44         if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))
45             ClusterSize = 2048;
46         else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))
47             ClusterSize = 512;
48         else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
49             ClusterSize = 1024;
50         else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))
51             ClusterSize = 2048;
52         else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))
53             ClusterSize = 4096;
54         else if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
55             ClusterSize = 8192;
56         else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
57             ClusterSize = 16384;
58         else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
59             ClusterSize = 32768;
60         else if (TotalNumberOfBytes->QuadPart <= (4096LL * 1024LL * 1024LL))
61             ClusterSize = 8192;
62         else
63             return FALSE;
64     }
65     else if (!wcsicmp(szFs, L"FAT32"))
66     {
67         if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))
68             ClusterSize = 512;
69         else if (TotalNumberOfBytes->QuadPart <= (128   * 1024 * 1024))
70             ClusterSize = 1024;
71         else if (TotalNumberOfBytes->QuadPart <= (256   * 1024 * 1024))
72             ClusterSize = 2048;
73         else if (TotalNumberOfBytes->QuadPart <= (8192LL  * 1024LL * 1024LL))
74             ClusterSize = 2048;
75         else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))
76             ClusterSize = 8192;
77         else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))
78             ClusterSize = 16384;
79         else
80             return FALSE;
81     }
82     else if (!wcsicmp(szFs, L"NTFS"))
83     {
84         if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))
85             ClusterSize = 512;
86         else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))
87             ClusterSize = 1024;
88         else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))
89             ClusterSize = 2048;
90         else
91             ClusterSize = 2048;
92     }
93     else if (!wcsicmp(szFs, L"EXT2"))
94     {
95         // auto block size calculation
96         ClusterSize = 0;
97     }
98     else if (!wcsicmp(szFs, L"BtrFS"))
99     {
100         // auto block size calculation
101         ClusterSize = 0;
102     }
103     else
104         return FALSE;
105 
106     *pClusterSize = ClusterSize;
107     return TRUE;
108 }
109 
110 typedef struct _DRIVE_PROP_PAGE
111 {
112     LPCSTR resname;
113     DLGPROC dlgproc;
114     UINT DriveType;
115 } DRIVE_PROP_PAGE;
116 
117 HRESULT
118 SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
119 {
120     HPSXA hpsx = NULL;
121     HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
122     PROPSHEETHEADERW psh;
123     CComObject<CDrvDefExt> *pDrvDefExt = NULL;
124     WCHAR wszName[256];
125 
126     ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
127     psh.dwSize = sizeof(PROPSHEETHEADERW);
128     psh.dwFlags = 0; // FIXME: make it modeless
129     psh.hwndParent = NULL;
130     psh.nStartPage = 0;
131     psh.phpage = hpsp;
132 
133     LPITEMIDLIST completePidl = ILCombine(pidlFolder, apidl[0]);
134     if (!completePidl)
135         return E_OUTOFMEMORY;
136 
137     if (ILGetDisplayNameExW(NULL, completePidl, wszName, ILGDN_NORMAL))
138     {
139         psh.pszCaption = wszName;
140         psh.dwFlags |= PSH_PROPTITLE;
141     }
142 
143     ILFree(completePidl);
144 
145     CComPtr<IDataObject> pDataObj;
146     HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
147 
148     if (SUCCEEDED(hr))
149     {
150         hr = CComObject<CDrvDefExt>::CreateInstance(&pDrvDefExt);
151         if (SUCCEEDED(hr))
152         {
153             pDrvDefExt->AddRef(); // CreateInstance returns object with 0 ref count
154             hr = pDrvDefExt->Initialize(pidlFolder, pDataObj, NULL);
155             if (SUCCEEDED(hr))
156             {
157                 hr = pDrvDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&psh);
158                 if (FAILED(hr))
159                     ERR("AddPages failed\n");
160             } else
161                 ERR("Initialize failed\n");
162         }
163 
164         hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", MAX_PROPERTY_SHEET_PAGE, pDataObj);
165         if (hpsx)
166             SHAddFromPropSheetExtArray(hpsx, (LPFNADDPROPSHEETPAGE)AddPropSheetPageCallback, (LPARAM)&psh);
167     }
168 
169     // NOTE: Currently property sheet is modal. If we make it modeless, then it returns HWND.
170     INT_PTR ret = PropertySheetW(&psh);
171 
172     if (hpsx)
173         SHDestroyPropSheetExtArray(hpsx);
174     if (pDrvDefExt)
175         pDrvDefExt->Release();
176 
177     if (ret > 0)
178         return S_OK;
179     if (ret == 0)
180         return S_FALSE;
181     return E_FAIL;
182 }
183 
184 static VOID
185 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
186 {
187     WCHAR wszBuf[100] = {0};
188     WCHAR szDrive[] = L"C:\\";
189     INT iSelIndex;
190     ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
191     DWORD ClusterSize;
192     LRESULT lIndex;
193     HWND hDlgCtrl;
194 
195     hDlgCtrl = GetDlgItem(hwndDlg, 28677);
196     iSelIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
197     if (iSelIndex == CB_ERR)
198         return;
199 
200     if (SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)wszBuf) == CB_ERR)
201         return;
202 
203     szDrive[0] = pContext->Drive + L'A';
204 
205     if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
206         return;
207 
208     if (!wcsicmp(wszBuf, L"FAT16") ||
209         !wcsicmp(wszBuf, L"FAT")) //REACTOS HACK
210     {
211         if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes))
212         {
213             TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes.QuadPart);
214             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
215             return;
216         }
217 
218         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszBuf, _countof(wszBuf)))
219         {
220             hDlgCtrl = GetDlgItem(hwndDlg, 28680);
221             SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
222             lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszBuf);
223             if (lIndex != CB_ERR)
224                 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
225             SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
226         }
227 
228         SendMessageW(GetDlgItem(hwndDlg, 28675), BM_SETCHECK, BST_UNCHECKED, 0);
229         EnableWindow(GetDlgItem(hwndDlg, 28675), FALSE);
230     }
231     else if (!wcsicmp(wszBuf, L"FAT32"))
232     {
233         if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes))
234         {
235             TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes.QuadPart);
236             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
237             return;
238         }
239 
240         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszBuf, _countof(wszBuf)))
241         {
242             hDlgCtrl = GetDlgItem(hwndDlg, 28680);
243             SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
244             lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszBuf);
245             if (lIndex != CB_ERR)
246                 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
247             SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
248         }
249 
250         SendMessageW(GetDlgItem(hwndDlg, 28675), BM_SETCHECK, BST_UNCHECKED, 0);
251         EnableWindow(GetDlgItem(hwndDlg, 28675), FALSE);
252     }
253     else if (!wcsicmp(wszBuf, L"NTFS"))
254     {
255         if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes))
256         {
257             TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes.QuadPart);
258             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
259             return;
260         }
261 
262         hDlgCtrl = GetDlgItem(hwndDlg, 28680);
263         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszBuf, _countof(wszBuf)))
264         {
265             SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
266             lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszBuf);
267             if (lIndex != CB_ERR)
268                 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
269             SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
270         }
271         ClusterSize = 512;
272         for (lIndex = 0; lIndex < 4; lIndex++)
273         {
274             TotalNumberOfBytes.QuadPart = ClusterSize;
275             if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, wszBuf, _countof(wszBuf)))
276             {
277                 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszBuf);
278                 if (lIndex != CB_ERR)
279                     SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
280             }
281             ClusterSize *= 2;
282         }
283 
284         EnableWindow(GetDlgItem(hwndDlg, 28675), TRUE);
285     }
286     else if (!wcsicmp(wszBuf, L"EXT2"))
287     {
288         if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes))
289         {
290             TRACE("EXT2 is not supported on hdd larger than 32T current %lu\n", TotalNumberOfBytes.QuadPart);
291             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
292             return;
293         }
294 
295         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszBuf, _countof(wszBuf)))
296         {
297             hDlgCtrl = GetDlgItem(hwndDlg, 28680);
298             SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
299             lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszBuf);
300             if (lIndex != CB_ERR)
301                 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
302             SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
303         }
304 
305         EnableWindow(GetDlgItem(hwndDlg, 28675), TRUE);
306     }
307     else if (!wcsicmp(wszBuf, L"BtrFS"))
308     {
309         if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes))
310         {
311             TRACE("BtrFS is not supported on hdd larger than 16E current %lu\n", TotalNumberOfBytes.QuadPart);
312             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);
313             return;
314         }
315 
316         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszBuf, _countof(wszBuf)))
317         {
318             hDlgCtrl = GetDlgItem(hwndDlg, 28680);
319             SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0);
320             lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszBuf);
321             if (lIndex != CB_ERR)
322                 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize);
323             SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0);
324         }
325 
326         EnableWindow(GetDlgItem(hwndDlg, 28675), TRUE);
327     }
328     else
329     {
330         FIXME("unknown fs\n");
331         SendDlgItemMessageW(hwndDlg, 28680, CB_RESETCONTENT, iSelIndex, 0);
332         return;
333     }
334 }
335 
336 static VOID
337 InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
338 {
339     WCHAR szText[120];
340     WCHAR szDrive[] = L"C:\\";
341     WCHAR szFs[30] = L"";
342     INT cchText;
343     ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;
344     DWORD dwIndex, dwDefault;
345     UCHAR uMinor, uMajor;
346     BOOLEAN Latest;
347     HWND hwndFileSystems;
348 
349     cchText = GetWindowTextW(hwndDlg, szText, _countof(szText) - 1);
350     if (cchText < 0)
351         cchText = 0;
352     szText[cchText++] = L' ';
353     szDrive[0] = pContext->Drive + L'A';
354     if (GetVolumeInformationW(szDrive, &szText[cchText], _countof(szText) - cchText, NULL, NULL, NULL, szFs, _countof(szFs)))
355     {
356         if (szText[cchText] == UNICODE_NULL)
357         {
358             /* load default volume label */
359             cchText += LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[cchText], _countof(szText) - cchText);
360         }
361         else
362         {
363             /* set volume label */
364             SetDlgItemTextW(hwndDlg, 28679, &szText[cchText]);
365             cchText += wcslen(&szText[cchText]);
366         }
367     }
368 
369     StringCchPrintfW(szText + cchText, _countof(szText) - cchText, L" (%c:)", szDrive[0]);
370 
371     /* set window text */
372     SetWindowTextW(hwndDlg, szText);
373 
374     if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL))
375     {
376         if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szText, _countof(szText)))
377         {
378             /* add drive capacity */
379             SendDlgItemMessageW(hwndDlg, 28673, CB_ADDSTRING, 0, (LPARAM)szText);
380             SendDlgItemMessageW(hwndDlg, 28673, CB_SETCURSEL, 0, (LPARAM)0);
381         }
382     }
383 
384     if (pContext->Options & SHFMT_OPT_FULL)
385     {
386         /* check quick format button */
387         SendDlgItemMessageW(hwndDlg, 28674, BM_SETCHECK, BST_CHECKED, 0);
388     }
389 
390     /* enumerate all available filesystems */
391     dwIndex = 0;
392     dwDefault = 0;
393     hwndFileSystems = GetDlgItem(hwndDlg, 28677);
394 
395     while(QueryAvailableFileSystemFormat(dwIndex, szText, &uMajor, &uMinor, &Latest))
396     {
397         if (!wcsicmp(szText, szFs))
398             dwDefault = dwIndex;
399 
400         SendMessageW(hwndFileSystems, CB_ADDSTRING, 0, (LPARAM)szText);
401         dwIndex++;
402     }
403 
404     if (!dwIndex)
405     {
406         ERR("no filesystem providers\n");
407         return;
408     }
409 
410     /* select default filesys */
411     SendMessageW(hwndFileSystems, CB_SETCURSEL, dwDefault, 0);
412     /* setup cluster combo */
413     InsertDefaultClusterSizeForFs(hwndDlg, pContext);
414 }
415 
416 static HWND FormatDrvDialog = NULL;
417 static BOOLEAN bSuccess = FALSE;
418 
419 static BOOLEAN NTAPI
420 FormatExCB(
421     IN CALLBACKCOMMAND Command,
422     IN ULONG SubAction,
423     IN PVOID ActionInfo)
424 {
425     PDWORD Progress;
426     PBOOLEAN pSuccess;
427     switch(Command)
428     {
429         case PROGRESS:
430             Progress = (PDWORD)ActionInfo;
431             SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, (WPARAM)*Progress, 0);
432             break;
433         case DONE:
434             pSuccess = (PBOOLEAN)ActionInfo;
435             bSuccess = (*pSuccess);
436             ShellMessageBoxW(shell32_hInstance, FormatDrvDialog, MAKEINTRESOURCEW(IDS_FORMAT_COMPLETE), MAKEINTRESOURCEW(IDS_FORMAT_TITLE), MB_OK | MB_ICONINFORMATION);
437             SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, 0, 0);
438             break;
439 
440         case VOLUMEINUSE:
441         case INSUFFICIENTRIGHTS:
442         case FSNOTSUPPORTED:
443         case CLUSTERSIZETOOSMALL:
444             bSuccess = FALSE;
445             FIXME("\n");
446             break;
447 
448         default:
449             break;
450     }
451 
452     return TRUE;
453 }
454 
455 VOID
456 FormatDrive(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
457 {
458     WCHAR szDrive[4] = { L'C', ':', '\\', 0 };
459     WCHAR szFileSys[40] = {0};
460     WCHAR szLabel[40] = {0};
461     INT iSelIndex;
462     UINT Length;
463     HWND hDlgCtrl;
464     BOOL QuickFormat;
465     DWORD ClusterSize;
466     DWORD DriveType;
467     FMIFS_MEDIA_FLAG MediaFlag = FMIFS_HARDDISK;
468 
469     /* set volume path */
470     szDrive[0] = pContext->Drive + L'A';
471 
472     /* get filesystem */
473     hDlgCtrl = GetDlgItem(hwndDlg, 28677);
474     iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
475     if (iSelIndex == CB_ERR)
476     {
477         FIXME("\n");
478         return;
479     }
480     Length = SendMessageW(hDlgCtrl, CB_GETLBTEXTLEN, iSelIndex, 0);
481     if ((int)Length == CB_ERR || Length + 1 > _countof(szFileSys))
482     {
483         FIXME("\n");
484         return;
485     }
486 
487     /* retrieve the file system */
488     SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFileSys);
489     szFileSys[_countof(szFileSys)-1] = L'\0';
490 
491     /* retrieve the volume label */
492     hDlgCtrl = GetWindow(hwndDlg, 28679);
493     Length = SendMessageW(hDlgCtrl, WM_GETTEXTLENGTH, 0, 0);
494     if (Length + 1 > _countof(szLabel))
495     {
496         FIXME("\n");
497         return;
498     }
499     SendMessageW(hDlgCtrl, WM_GETTEXT, _countof(szLabel), (LPARAM)szLabel);
500     szLabel[(sizeof(szLabel)/sizeof(WCHAR))-1] = L'\0';
501 
502     /* check for quickformat */
503     if (SendDlgItemMessageW(hwndDlg, 28674, BM_GETCHECK, 0, 0) == BST_CHECKED)
504         QuickFormat = TRUE;
505     else
506         QuickFormat = FALSE;
507 
508     /* get the cluster size */
509     hDlgCtrl = GetDlgItem(hwndDlg, 28680);
510     iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
511     if (iSelIndex == CB_ERR)
512     {
513         FIXME("\n");
514         return;
515     }
516     ClusterSize = SendMessageW(hDlgCtrl, CB_GETITEMDATA, iSelIndex, 0);
517     if ((int)ClusterSize == CB_ERR)
518     {
519         FIXME("\n");
520         return;
521     }
522 
523     hDlgCtrl = GetDlgItem(hwndDlg, 28680);
524     SendMessageW(hDlgCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
525     bSuccess = FALSE;
526 
527     /* FIXME
528      * will cause display problems
529      * when performing more than one format
530      */
531     FormatDrvDialog = hwndDlg;
532 
533     /* See if the drive is removable or not */
534     DriveType = GetDriveTypeW(szDrive);
535     switch (DriveType)
536     {
537         case DRIVE_UNKNOWN:
538         case DRIVE_REMOTE:
539         case DRIVE_CDROM:
540         case DRIVE_NO_ROOT_DIR:
541         {
542             FIXME("\n");
543             return;
544         }
545 
546         case DRIVE_REMOVABLE:
547             MediaFlag = FMIFS_FLOPPY;
548             break;
549 
550         case DRIVE_FIXED:
551         case DRIVE_RAMDISK:
552             MediaFlag = FMIFS_HARDDISK;
553             break;
554     }
555 
556     /* Format the drive */
557     FormatEx(szDrive,
558              MediaFlag,
559              szFileSys,
560              szLabel,
561              QuickFormat,
562              ClusterSize,
563              FormatExCB);
564 
565     FormatDrvDialog = NULL;
566     if (!bSuccess)
567     {
568         pContext->Result = SHFMT_ERROR;
569     }
570     else if (QuickFormat)
571     {
572         pContext->Result = SHFMT_OPT_FULL;
573     }
574     else
575     {
576         pContext->Result = FALSE;
577     }
578 }
579 
580 static INT_PTR CALLBACK
581 FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
582 {
583     PFORMAT_DRIVE_CONTEXT pContext;
584 
585     switch(uMsg)
586     {
587         case WM_INITDIALOG:
588             InitializeFormatDriveDlg(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);
589             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
590             return TRUE;
591         case WM_COMMAND:
592             switch(LOWORD(wParam))
593             {
594                 case IDOK:
595                     if (ShellMessageBoxW(shell32_hInstance, hwndDlg, MAKEINTRESOURCEW(IDS_FORMAT_WARNING), MAKEINTRESOURCEW(IDS_FORMAT_TITLE), MB_OKCANCEL | MB_ICONWARNING) == IDOK)
596                     {
597                         pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
598                         FormatDrive(hwndDlg, pContext);
599                     }
600                     break;
601                 case IDCANCEL:
602                     pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
603                     EndDialog(hwndDlg, pContext->Result);
604                     break;
605                 case 28677: // filesystem combo
606                     if (HIWORD(wParam) == CBN_SELENDOK)
607                     {
608                         pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER);
609                         InsertDefaultClusterSizeForFs(hwndDlg, pContext);
610                     }
611                     break;
612             }
613     }
614     return FALSE;
615 }
616 
617 /*************************************************************************
618  *              SHFormatDrive (SHELL32.@)
619  */
620 
621 DWORD
622 WINAPI
623 SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options)
624 {
625     FORMAT_DRIVE_CONTEXT Context;
626     int result;
627 
628     TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd, drive, fmtID, options);
629 
630     Context.Drive = drive;
631     Context.Options = options;
632 
633     result = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_FORMAT_DRIVE), hwnd, FormatDriveDlg, (LPARAM)&Context);
634 
635     return result;
636 }
637 
638 
639