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