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