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 } 723