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 return E_FAIL; 232 } 233 234 static VOID 235 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext) 236 { 237 WCHAR wszBuf[100] = {0}; 238 WCHAR wszDefaultSize[100] = {0}; 239 PCWSTR pwszFsSizeLimit; 240 WCHAR szDrive[] = L"C:\\"; 241 INT iSelIndex; 242 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes; 243 DWORD ClusterSize; 244 LRESULT lIndex; 245 HWND hDlgCtrl; 246 247 hDlgCtrl = GetDlgItem(hwndDlg, 28677); 248 iSelIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0); 249 if (iSelIndex == CB_ERR) 250 return; 251 252 if (SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)wszBuf) == CB_ERR) 253 return; 254 255 szDrive[0] = pContext->Drive + L'A'; 256 257 if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL)) 258 return; 259 260 if (!wcsicmp(wszBuf, L"FAT16") || 261 !wcsicmp(wszBuf, L"FAT")) // REACTOS HACK 262 { 263 pwszFsSizeLimit = L"4GB"; 264 } 265 else if (!wcsicmp(wszBuf, L"FAT32")) 266 { 267 pwszFsSizeLimit = L"32GB"; 268 } 269 else if (!wcsicmp(wszBuf, L"FATX")) 270 { 271 pwszFsSizeLimit = L"1GB/32GB"; 272 } 273 else if (!wcsicmp(wszBuf, L"NTFS")) 274 { 275 pwszFsSizeLimit = L"256TB"; 276 } 277 else if (!wcsicmp(wszBuf, L"EXT2")) 278 { 279 pwszFsSizeLimit = L"32TB"; 280 } 281 else 282 { 283 pwszFsSizeLimit = L"16EB"; 284 } 285 286 if (!wcsicmp(wszBuf, L"FAT16") || 287 !wcsicmp(wszBuf, L"FAT") || // REACTOS HACK 288 !wcsicmp(wszBuf, L"FAT32") || 289 !wcsicmp(wszBuf, L"FATX") || 290 !wcsicmp(wszBuf, L"NTFS") || 291 !wcsicmp(wszBuf, L"EXT2") || 292 !wcsicmp(wszBuf, L"BtrFS")) 293 { 294 if (!GetDefaultClusterSize(wszBuf, &ClusterSize, &TotalNumberOfBytes)) 295 { 296 TRACE("%S is not supported on drive larger than %S, current size: %lu\n", wszBuf, pwszFsSizeLimit, TotalNumberOfBytes.QuadPart); 297 SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0); 298 return; 299 } 300 301 if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, wszDefaultSize, _countof(wszDefaultSize))) 302 { 303 hDlgCtrl = GetDlgItem(hwndDlg, 28680); // Get the window handle of "allocation unit size" combobox 304 SendMessageW(hDlgCtrl, CB_RESETCONTENT, 0, 0); 305 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszDefaultSize); 306 if (lIndex != CB_ERR) 307 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize); 308 SendMessageW(hDlgCtrl, CB_SETCURSEL, 0, 0); 309 } 310 311 if (!wcsicmp(wszBuf, L"NTFS")) 312 { 313 ClusterSize = 512; 314 for (lIndex = 0; lIndex < 4; lIndex++) 315 { 316 TotalNumberOfBytes.QuadPart = ClusterSize; 317 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, wszDefaultSize, _countof(wszDefaultSize))) 318 { 319 lIndex = SendMessageW(hDlgCtrl, CB_ADDSTRING, 0, (LPARAM)wszDefaultSize); 320 if (lIndex != CB_ERR) 321 SendMessageW(hDlgCtrl, CB_SETITEMDATA, lIndex, (LPARAM)ClusterSize); 322 } 323 ClusterSize *= 2; 324 } 325 } 326 327 SendMessageW(GetDlgItem(hwndDlg, 28675), BM_SETCHECK, BST_UNCHECKED, 0); 328 if (!wcsicmp(wszBuf, L"EXT2") || 329 !wcsicmp(wszBuf, L"BtrFS") || 330 !wcsicmp(wszBuf, L"NTFS")) 331 { 332 /* Enable the "Enable Compression" button */ 333 EnableWindow(GetDlgItem(hwndDlg, 28675), TRUE); 334 } 335 else 336 { 337 /* Disable the "Enable Compression" button */ 338 EnableWindow(GetDlgItem(hwndDlg, 28675), FALSE); 339 } 340 } 341 else 342 { 343 FIXME("Unknown filesystem: %ls\n", wszBuf); 344 SendDlgItemMessageW(hwndDlg, 28680, CB_RESETCONTENT, iSelIndex, 0); 345 return; 346 } 347 } 348 349 static VOID 350 InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext) 351 { 352 WCHAR szText[120]; 353 WCHAR szDrive[] = L"C:\\"; 354 WCHAR szFs[30] = L""; 355 INT cchText; 356 ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes; 357 DWORD dwIndex, dwDefault; 358 UCHAR uMinor, uMajor; 359 BOOLEAN Latest; 360 HWND hwndFileSystems; 361 362 cchText = GetWindowTextW(hwndDlg, szText, _countof(szText) - 1); 363 if (cchText < 0) 364 cchText = 0; 365 szText[cchText++] = L' '; 366 szDrive[0] = pContext->Drive + L'A'; 367 if (GetVolumeInformationW(szDrive, &szText[cchText], _countof(szText) - cchText, NULL, NULL, NULL, szFs, _countof(szFs))) 368 { 369 if (szText[cchText] == UNICODE_NULL) 370 { 371 /* load default volume label */ 372 cchText += LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[cchText], _countof(szText) - cchText); 373 } 374 else 375 { 376 /* set volume label */ 377 SetDlgItemTextW(hwndDlg, 28679, &szText[cchText]); 378 cchText += wcslen(&szText[cchText]); 379 } 380 } 381 382 StringCchPrintfW(szText + cchText, _countof(szText) - cchText, L" (%c:)", szDrive[0]); 383 384 /* set window text */ 385 SetWindowTextW(hwndDlg, szText); 386 387 if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfBytes, NULL)) 388 { 389 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szText, _countof(szText))) 390 { 391 /* add drive capacity */ 392 SendDlgItemMessageW(hwndDlg, 28673, CB_ADDSTRING, 0, (LPARAM)szText); 393 SendDlgItemMessageW(hwndDlg, 28673, CB_SETCURSEL, 0, (LPARAM)0); 394 } 395 } 396 397 if (pContext->Options & SHFMT_OPT_FULL) 398 { 399 /* check quick format button */ 400 SendDlgItemMessageW(hwndDlg, 28674, BM_SETCHECK, BST_CHECKED, 0); 401 } 402 403 /* enumerate all available filesystems */ 404 dwIndex = 0; 405 dwDefault = 0; 406 hwndFileSystems = GetDlgItem(hwndDlg, 28677); 407 408 while(QueryAvailableFileSystemFormat(dwIndex, szText, &uMajor, &uMinor, &Latest)) 409 { 410 if (!wcsicmp(szText, szFs)) 411 dwDefault = dwIndex; 412 413 SendMessageW(hwndFileSystems, CB_ADDSTRING, 0, (LPARAM)szText); 414 dwIndex++; 415 } 416 417 if (!dwIndex) 418 { 419 ERR("no filesystem providers\n"); 420 return; 421 } 422 423 /* select default filesys */ 424 SendMessageW(hwndFileSystems, CB_SETCURSEL, dwDefault, 0); 425 /* setup cluster combo */ 426 InsertDefaultClusterSizeForFs(hwndDlg, pContext); 427 } 428 429 static HWND FormatDrvDialog = NULL; 430 static BOOLEAN bSuccess = FALSE; 431 432 static BOOLEAN NTAPI 433 FormatExCB( 434 IN CALLBACKCOMMAND Command, 435 IN ULONG SubAction, 436 IN PVOID ActionInfo) 437 { 438 PDWORD Progress; 439 PBOOLEAN pSuccess; 440 switch(Command) 441 { 442 case PROGRESS: 443 Progress = (PDWORD)ActionInfo; 444 SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, (WPARAM)*Progress, 0); 445 break; 446 case DONE: 447 pSuccess = (PBOOLEAN)ActionInfo; 448 bSuccess = (*pSuccess); 449 ShellMessageBoxW(shell32_hInstance, FormatDrvDialog, MAKEINTRESOURCEW(IDS_FORMAT_COMPLETE), MAKEINTRESOURCEW(IDS_FORMAT_TITLE), MB_OK | MB_ICONINFORMATION); 450 SendDlgItemMessageW(FormatDrvDialog, 28678, PBM_SETPOS, 0, 0); 451 break; 452 453 case VOLUMEINUSE: 454 case INSUFFICIENTRIGHTS: 455 case FSNOTSUPPORTED: 456 case CLUSTERSIZETOOSMALL: 457 bSuccess = FALSE; 458 FIXME("Unsupported command in FormatExCB\n"); 459 break; 460 461 default: 462 break; 463 } 464 465 return TRUE; 466 } 467 468 VOID 469 FormatDrive(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext) 470 { 471 WCHAR szDrive[4] = { L'C', ':', '\\', 0 }; 472 WCHAR szFileSys[40] = {0}; 473 WCHAR szLabel[40] = {0}; 474 INT iSelIndex; 475 UINT Length; 476 HWND hDlgCtrl; 477 BOOL QuickFormat; 478 DWORD ClusterSize; 479 DWORD DriveType; 480 FMIFS_MEDIA_FLAG MediaFlag = FMIFS_HARDDISK; 481 482 /* set volume path */ 483 szDrive[0] = pContext->Drive + L'A'; 484 485 /* get filesystem */ 486 hDlgCtrl = GetDlgItem(hwndDlg, 28677); 487 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0); 488 if (iSelIndex == CB_ERR) 489 { 490 ERR("Unable to get file system selection\n"); 491 return; 492 } 493 Length = SendMessageW(hDlgCtrl, CB_GETLBTEXTLEN, iSelIndex, 0); 494 if ((int)Length == CB_ERR || Length + 1 > _countof(szFileSys)) 495 { 496 ERR("Unable to get file system selection\n"); 497 return; 498 } 499 500 /* retrieve the file system */ 501 SendMessageW(hDlgCtrl, CB_GETLBTEXT, iSelIndex, (LPARAM)szFileSys); 502 szFileSys[_countof(szFileSys)-1] = L'\0'; 503 504 /* retrieve the volume label */ 505 hDlgCtrl = GetWindow(hwndDlg, 28679); 506 Length = SendMessageW(hDlgCtrl, WM_GETTEXTLENGTH, 0, 0); 507 if (Length + 1 > _countof(szLabel)) 508 { 509 ERR("Unable to get volume label\n"); 510 return; 511 } 512 SendMessageW(hDlgCtrl, WM_GETTEXT, _countof(szLabel), (LPARAM)szLabel); 513 szLabel[(sizeof(szLabel)/sizeof(WCHAR))-1] = L'\0'; 514 515 /* check for quickformat */ 516 if (SendDlgItemMessageW(hwndDlg, 28674, BM_GETCHECK, 0, 0) == BST_CHECKED) 517 QuickFormat = TRUE; 518 else 519 QuickFormat = FALSE; 520 521 /* get the cluster size */ 522 hDlgCtrl = GetDlgItem(hwndDlg, 28680); 523 iSelIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0); 524 if (iSelIndex == CB_ERR) 525 { 526 FIXME("\n"); 527 return; 528 } 529 ClusterSize = SendMessageW(hDlgCtrl, CB_GETITEMDATA, iSelIndex, 0); 530 if ((int)ClusterSize == CB_ERR) 531 { 532 FIXME("\n"); 533 return; 534 } 535 536 hDlgCtrl = GetDlgItem(hwndDlg, 28680); 537 SendMessageW(hDlgCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); 538 bSuccess = FALSE; 539 540 /* FIXME 541 * will cause display problems 542 * when performing more than one format 543 */ 544 FormatDrvDialog = hwndDlg; 545 546 /* See if the drive is removable or not */ 547 DriveType = GetDriveTypeW(szDrive); 548 switch (DriveType) 549 { 550 case DRIVE_UNKNOWN: 551 case DRIVE_REMOTE: 552 case DRIVE_CDROM: 553 case DRIVE_NO_ROOT_DIR: 554 { 555 FIXME("\n"); 556 return; 557 } 558 559 case DRIVE_REMOVABLE: 560 MediaFlag = FMIFS_FLOPPY; 561 break; 562 563 case DRIVE_FIXED: 564 case DRIVE_RAMDISK: 565 MediaFlag = FMIFS_HARDDISK; 566 break; 567 } 568 569 /* Format the drive */ 570 FormatEx(szDrive, 571 MediaFlag, 572 szFileSys, 573 szLabel, 574 QuickFormat, 575 ClusterSize, 576 FormatExCB); 577 578 FormatDrvDialog = NULL; 579 if (!bSuccess) 580 { 581 pContext->Result = SHFMT_ERROR; 582 } 583 else if (QuickFormat) 584 { 585 pContext->Result = SHFMT_OPT_FULL; 586 } 587 else 588 { 589 pContext->Result = FALSE; 590 } 591 } 592 593 struct FORMAT_DRIVE_PARAMS 594 { 595 HWND hwndDlg; 596 PFORMAT_DRIVE_CONTEXT pContext; 597 }; 598 599 static unsigned __stdcall DoFormatDrive(void *args) 600 { 601 FORMAT_DRIVE_PARAMS *pParams = reinterpret_cast<FORMAT_DRIVE_PARAMS *>(args); 602 HWND hwndDlg = pParams->hwndDlg; 603 PFORMAT_DRIVE_CONTEXT pContext = pParams->pContext; 604 605 /* Disable controls during format */ 606 HMENU hSysMenu = GetSystemMenu(hwndDlg, FALSE); 607 EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); 608 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); 609 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE); 610 EnableWindow(GetDlgItem(hwndDlg, 28673), FALSE); 611 EnableWindow(GetDlgItem(hwndDlg, 28677), FALSE); 612 EnableWindow(GetDlgItem(hwndDlg, 28680), FALSE); 613 EnableWindow(GetDlgItem(hwndDlg, 28679), FALSE); 614 EnableWindow(GetDlgItem(hwndDlg, 28674), FALSE); 615 616 FormatDrive(hwndDlg, pContext); 617 618 /* Re-enable controls after format */ 619 EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); 620 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), TRUE); 621 EnableWindow(GetDlgItem(hwndDlg, 28673), TRUE); 622 EnableWindow(GetDlgItem(hwndDlg, 28677), TRUE); 623 EnableWindow(GetDlgItem(hwndDlg, 28680), TRUE); 624 EnableWindow(GetDlgItem(hwndDlg, 28679), TRUE); 625 EnableWindow(GetDlgItem(hwndDlg, 28674), TRUE); 626 EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED); 627 pContext->bFormattingNow = FALSE; 628 629 delete pParams; 630 return 0; 631 } 632 633 static INT_PTR CALLBACK 634 FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 635 { 636 PFORMAT_DRIVE_CONTEXT pContext; 637 638 switch(uMsg) 639 { 640 case WM_INITDIALOG: 641 InitializeFormatDriveDlg(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam); 642 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam); 643 return TRUE; 644 case WM_COMMAND: 645 switch(LOWORD(wParam)) 646 { 647 case IDOK: 648 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER); 649 if (pContext->bFormattingNow) 650 break; 651 652 if (ShellMessageBoxW(shell32_hInstance, hwndDlg, 653 MAKEINTRESOURCEW(IDS_FORMAT_WARNING), 654 MAKEINTRESOURCEW(IDS_FORMAT_TITLE), 655 MB_OKCANCEL | MB_ICONWARNING) == IDOK) 656 { 657 pContext->bFormattingNow = TRUE; 658 659 FORMAT_DRIVE_PARAMS *pParams = new FORMAT_DRIVE_PARAMS; 660 pParams->hwndDlg = hwndDlg; 661 pParams->pContext = pContext; 662 663 unsigned tid; 664 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, DoFormatDrive, pParams, 0, &tid); 665 CloseHandle(hThread); 666 } 667 break; 668 case IDCANCEL: 669 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER); 670 if (pContext->bFormattingNow) 671 break; 672 673 EndDialog(hwndDlg, pContext->Result); 674 break; 675 case 28677: // filesystem combo 676 if (HIWORD(wParam) == CBN_SELENDOK) 677 { 678 pContext = (PFORMAT_DRIVE_CONTEXT)GetWindowLongPtr(hwndDlg, DWLP_USER); 679 if (pContext->bFormattingNow) 680 break; 681 682 InsertDefaultClusterSizeForFs(hwndDlg, pContext); 683 } 684 break; 685 } 686 } 687 return FALSE; 688 } 689 690 /************************************************************************* 691 * SHFormatDrive (SHELL32.@) 692 */ 693 694 DWORD 695 WINAPI 696 SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options) 697 { 698 FORMAT_DRIVE_CONTEXT Context; 699 int result; 700 701 TRACE("%p, 0x%08x, 0x%08x, 0x%08x - stub\n", hwnd, drive, fmtID, options); 702 703 Context.Drive = drive; 704 Context.Options = options; 705 Context.Result = FALSE; 706 Context.bFormattingNow = FALSE; 707 708 if (!IsSystemDrive(&Context)) 709 { 710 result = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_FORMAT_DRIVE), hwnd, FormatDriveDlg, (LPARAM)&Context); 711 } 712 else 713 { 714 result = SHFMT_ERROR; 715 ShellMessageBoxW(shell32_hInstance, hwnd, MAKEINTRESOURCEW(IDS_NO_FORMAT), MAKEINTRESOURCEW(IDS_NO_FORMAT_TITLE), MB_OK | MB_ICONWARNING); 716 TRACE("SHFormatDrive(): The provided drive for format is a system volume! Aborting...\n"); 717 } 718 719 return result; 720 } 721