1 /* 2 * Provides default drive shell extension 3 * 4 * Copyright 2005 Johannes Anderwald 5 * Copyright 2012 Rafal Harabien 6 * Copyright 2020 Katayama Hirofumi MZ 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include "precomp.h" 24 25 #define _USE_MATH_DEFINES 26 #include <math.h> 27 #include <devguid.h> 28 29 #define NTOS_MODE_USER 30 #include <ndk/iofuncs.h> 31 #include <ndk/obfuncs.h> 32 33 WINE_DEFAULT_DEBUG_CHANNEL(shell); 34 35 typedef enum 36 { 37 HWPD_STANDARDLIST = 0, 38 HWPD_LARGELIST, 39 HWPD_MAX = HWPD_LARGELIST 40 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE; 41 42 EXTERN_C HWND WINAPI 43 DeviceCreateHardwarePageEx(HWND hWndParent, 44 LPGUID lpGuids, 45 UINT uNumberOfGuids, 46 HWPAGE_DISPLAYMODE DisplayMode); 47 UINT SH_FormatByteSize(LONGLONG cbSize, LPWSTR pwszResult, UINT cchResultMax); 48 49 static VOID 50 GetDriveNameWithLetter(LPWSTR pwszText, UINT cchTextMax, LPCWSTR pwszDrive) 51 { 52 DWORD dwMaxComp, dwFileSys; 53 SIZE_T cchText = 0; 54 55 if (GetVolumeInformationW(pwszDrive, pwszText, cchTextMax, NULL, &dwMaxComp, &dwFileSys, NULL, 0)) 56 { 57 cchText = wcslen(pwszText); 58 if (cchText == 0) 59 { 60 /* load default volume label */ 61 cchText = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, pwszText, cchTextMax); 62 } 63 } 64 65 StringCchPrintfW(pwszText + cchText, cchTextMax - cchText, L" (%c:)", pwszDrive[0]); 66 } 67 68 static VOID 69 InitializeChkDskDialog(HWND hwndDlg, LPCWSTR pwszDrive) 70 { 71 WCHAR wszText[100]; 72 UINT Length; 73 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pwszDrive); 74 75 Length = GetWindowTextW(hwndDlg, wszText, sizeof(wszText) / sizeof(WCHAR)); 76 wszText[Length] = L' '; 77 GetDriveNameWithLetter(&wszText[Length + 1], (sizeof(wszText) / sizeof(WCHAR)) - Length - 1, pwszDrive); 78 SetWindowText(hwndDlg, wszText); 79 } 80 81 static HWND hChkdskDrvDialog = NULL; 82 static BOOLEAN bChkdskSuccess = FALSE; 83 84 static BOOLEAN NTAPI 85 ChkdskCallback( 86 IN CALLBACKCOMMAND Command, 87 IN ULONG SubAction, 88 IN PVOID ActionInfo) 89 { 90 PDWORD Progress; 91 PBOOLEAN pSuccess; 92 switch(Command) 93 { 94 case PROGRESS: 95 Progress = (PDWORD)ActionInfo; 96 SendDlgItemMessageW(hChkdskDrvDialog, 14002, PBM_SETPOS, (WPARAM)*Progress, 0); 97 break; 98 case DONE: 99 pSuccess = (PBOOLEAN)ActionInfo; 100 bChkdskSuccess = (*pSuccess); 101 break; 102 103 case VOLUMEINUSE: 104 case INSUFFICIENTRIGHTS: 105 case FSNOTSUPPORTED: 106 case CLUSTERSIZETOOSMALL: 107 bChkdskSuccess = FALSE; 108 FIXME("\n"); 109 break; 110 111 default: 112 break; 113 } 114 115 return TRUE; 116 } 117 118 static VOID 119 ChkDskNow(HWND hwndDlg, LPCWSTR pwszDrive) 120 { 121 //DWORD ClusterSize = 0; 122 WCHAR wszFs[30]; 123 ULARGE_INTEGER TotalNumberOfFreeBytes, FreeBytesAvailableUser; 124 BOOLEAN bCorrectErrors = FALSE, bScanDrive = FALSE; 125 126 if(!GetVolumeInformationW(pwszDrive, NULL, 0, NULL, NULL, NULL, wszFs, _countof(wszFs))) 127 { 128 FIXME("failed to get drive fs type\n"); 129 return; 130 } 131 132 if (!GetDiskFreeSpaceExW(pwszDrive, &FreeBytesAvailableUser, &TotalNumberOfFreeBytes, NULL)) 133 { 134 FIXME("failed to get drive space type\n"); 135 return; 136 } 137 138 /*if (!GetDefaultClusterSize(wszFs, &ClusterSize, &TotalNumberOfFreeBytes)) 139 { 140 FIXME("invalid cluster size\n"); 141 return; 142 }*/ 143 144 if (SendDlgItemMessageW(hwndDlg, 14000, BM_GETCHECK, 0, 0) == BST_CHECKED) 145 bCorrectErrors = TRUE; 146 147 if (SendDlgItemMessageW(hwndDlg, 14001, BM_GETCHECK, 0, 0) == BST_CHECKED) 148 bScanDrive = TRUE; 149 150 hChkdskDrvDialog = hwndDlg; 151 bChkdskSuccess = FALSE; 152 SendDlgItemMessageW(hwndDlg, 14002, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); 153 Chkdsk((LPWSTR)pwszDrive, (LPWSTR)wszFs, bCorrectErrors, TRUE, FALSE, bScanDrive, NULL, NULL, ChkdskCallback); // FIXME: casts 154 155 hChkdskDrvDialog = NULL; 156 bChkdskSuccess = FALSE; 157 } 158 159 static INT_PTR CALLBACK 160 ChkDskDlg( 161 HWND hwndDlg, 162 UINT uMsg, 163 WPARAM wParam, 164 LPARAM lParam) 165 { 166 switch(uMsg) 167 { 168 case WM_INITDIALOG: 169 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam); 170 InitializeChkDskDialog(hwndDlg, (LPCWSTR)lParam); 171 return TRUE; 172 case WM_COMMAND: 173 switch(LOWORD(wParam)) 174 { 175 case IDCANCEL: 176 EndDialog(hwndDlg, 0); 177 break; 178 case IDOK: 179 { 180 LPCWSTR pwszDrive = (LPCWSTR)GetWindowLongPtr(hwndDlg, DWLP_USER); 181 ChkDskNow(hwndDlg, pwszDrive); 182 break; 183 } 184 } 185 break; 186 } 187 188 return FALSE; 189 } 190 191 VOID 192 CDrvDefExt::PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT pDrawItem) 193 { 194 HBRUSH hBrush; 195 196 if (pDrawItem->CtlID == 14013) 197 { 198 hBrush = CreateSolidBrush(RGB(0, 0, 255)); 199 if (hBrush) 200 { 201 FillRect(pDrawItem->hDC, &pDrawItem->rcItem, hBrush); 202 DeleteObject((HGDIOBJ)hBrush); 203 } 204 } 205 else if (pDrawItem->CtlID == 14014) 206 { 207 hBrush = CreateSolidBrush(RGB(255, 0, 255)); 208 if (hBrush) 209 { 210 FillRect(pDrawItem->hDC, &pDrawItem->rcItem, hBrush); 211 DeleteObject((HGDIOBJ)hBrush); 212 } 213 } 214 else if (pDrawItem->CtlID == 14015) 215 { 216 HBRUSH hBlueBrush = CreateSolidBrush(RGB(0, 0, 255)); 217 HBRUSH hMagBrush = CreateSolidBrush(RGB(255, 0, 255)); 218 HBRUSH hbrOld; 219 HPEN hBlackPen = (HPEN)GetStockObject(BLACK_PEN); 220 HPEN hDarkBluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 128)); 221 HPEN hDarkMagPen = CreatePen(PS_SOLID, 1, RGB(128, 0, 128)); 222 HPEN hOldPen = (HPEN)SelectObject(pDrawItem->hDC, hDarkMagPen); 223 INT xCenter = (pDrawItem->rcItem.left + pDrawItem->rcItem.right) / 2; 224 INT yCenter = (pDrawItem->rcItem.top + pDrawItem->rcItem.bottom - 10) / 2; 225 INT cx = pDrawItem->rcItem.right - pDrawItem->rcItem.left; 226 INT cy = pDrawItem->rcItem.bottom - pDrawItem->rcItem.top - 10; 227 INT xRadial = xCenter + (INT)(cos(M_PI + m_FreeSpacePerc / 100.0f * M_PI * 2.0f) * cx / 2); 228 INT yRadial = yCenter - (INT)(sin(M_PI + m_FreeSpacePerc / 100.0f * M_PI * 2.0f) * cy / 2); 229 230 TRACE("FreeSpace %u a %f cx %d\n", m_FreeSpacePerc, M_PI+m_FreeSpacePerc / 100.0f * M_PI * 2.0f, cx); 231 232 for (INT x = pDrawItem->rcItem.left; x < pDrawItem->rcItem.right; ++x) 233 { 234 double cos_val = (x - xCenter) * 2.0f / cx; 235 INT y = yCenter + (INT)(sin(acos(cos_val)) * cy / 2) - 1; 236 HPEN hCenterPen; 237 238 if (m_FreeSpacePerc < 50 && x == xRadial) 239 SelectObject(pDrawItem->hDC, hDarkBluePen); 240 241 /* Temporarily change pens to draw edges */ 242 if (x == pDrawItem->rcItem.left) 243 hCenterPen = (HPEN)SelectObject(pDrawItem->hDC, hBlackPen); 244 else if (x == pDrawItem->rcItem.right - 1) 245 SelectObject(pDrawItem->hDC, hBlackPen); 246 247 MoveToEx(pDrawItem->hDC, x, y, NULL); 248 LineTo(pDrawItem->hDC, x, y + 10); 249 SetPixel(pDrawItem->hDC, x, y + 10, RGB(0, 0, 0)); 250 251 /* Restore fill section pens */ 252 if (x == pDrawItem->rcItem.left) 253 SelectObject(pDrawItem->hDC, hCenterPen); 254 } 255 256 SelectObject(pDrawItem->hDC, hBlackPen); 257 258 if (m_FreeSpacePerc > 50) 259 { 260 hbrOld = (HBRUSH)SelectObject(pDrawItem->hDC, hMagBrush); 261 262 Ellipse(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, 263 pDrawItem->rcItem.right, pDrawItem->rcItem.bottom - 10); 264 265 SelectObject(pDrawItem->hDC, hBlueBrush); 266 267 if (m_FreeSpacePerc < 100) 268 { 269 Pie(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, pDrawItem->rcItem.right, 270 pDrawItem->rcItem.bottom - 10, xRadial, yRadial, pDrawItem->rcItem.left, yCenter); 271 } 272 } 273 else 274 { 275 hbrOld = (HBRUSH)SelectObject(pDrawItem->hDC, hBlueBrush); 276 277 Ellipse(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, 278 pDrawItem->rcItem.right, pDrawItem->rcItem.bottom - 10); 279 280 SelectObject(pDrawItem->hDC, hMagBrush); 281 282 if (m_FreeSpacePerc > 0) 283 { 284 Pie(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, pDrawItem->rcItem.right, 285 pDrawItem->rcItem.bottom - 10, pDrawItem->rcItem.left, yCenter, xRadial, yRadial); 286 } 287 } 288 289 SelectObject(pDrawItem->hDC, hbrOld); 290 SelectObject(pDrawItem->hDC, hOldPen); 291 292 DeleteObject(hBlueBrush); 293 DeleteObject(hMagBrush); 294 DeleteObject(hDarkBluePen); 295 DeleteObject(hDarkMagPen); 296 } 297 } 298 299 // https://stackoverflow.com/questions/3098696/get-information-about-disk-drives-result-on-windows7-32-bit-system/3100268#3100268 300 static BOOL 301 GetDriveTypeAndCharacteristics(HANDLE hDevice, DEVICE_TYPE *pDeviceType, ULONG *pCharacteristics) 302 { 303 NTSTATUS Status; 304 IO_STATUS_BLOCK IoStatusBlock; 305 FILE_FS_DEVICE_INFORMATION DeviceInfo; 306 307 Status = NtQueryVolumeInformationFile(hDevice, &IoStatusBlock, 308 &DeviceInfo, sizeof(DeviceInfo), 309 FileFsDeviceInformation); 310 if (Status == NO_ERROR) 311 { 312 *pDeviceType = DeviceInfo.DeviceType; 313 *pCharacteristics = DeviceInfo.Characteristics; 314 return TRUE; 315 } 316 317 return FALSE; 318 } 319 320 BOOL IsDriveFloppyW(LPCWSTR pszDriveRoot) 321 { 322 LPCWSTR RootPath = pszDriveRoot; 323 WCHAR szRoot[16], szDeviceName[16]; 324 UINT uType; 325 HANDLE hDevice; 326 DEVICE_TYPE DeviceType; 327 ULONG ulCharacteristics; 328 BOOL ret; 329 330 lstrcpynW(szRoot, RootPath, _countof(szRoot)); 331 332 if (L'a' <= szRoot[0] && szRoot[0] <= 'z') 333 { 334 szRoot[0] += ('A' - 'a'); 335 } 336 337 if ('A' <= szRoot[0] && szRoot[0] <= L'Z' && 338 szRoot[1] == L':' && szRoot[2] == 0) 339 { 340 // 'C:' --> 'C:\' 341 szRoot[2] = L'\\'; 342 szRoot[3] = 0; 343 } 344 345 if (!PathIsRootW(szRoot)) 346 { 347 return FALSE; 348 } 349 350 uType = GetDriveTypeW(szRoot); 351 if (uType == DRIVE_REMOVABLE) 352 { 353 if (szRoot[0] == L'A' || szRoot[0] == L'B') 354 return TRUE; 355 } 356 else 357 { 358 return FALSE; 359 } 360 361 lstrcpynW(szDeviceName, L"\\\\.\\", _countof(szDeviceName)); 362 szDeviceName[4] = szRoot[0]; 363 szDeviceName[5] = L':'; 364 szDeviceName[6] = UNICODE_NULL; 365 366 hDevice = CreateFileW(szDeviceName, FILE_READ_ATTRIBUTES, 367 FILE_SHARE_READ | FILE_SHARE_WRITE, 368 NULL, OPEN_EXISTING, 0, NULL); 369 if (hDevice == INVALID_HANDLE_VALUE) 370 { 371 return FALSE; 372 } 373 374 ret = FALSE; 375 if (GetDriveTypeAndCharacteristics(hDevice, &DeviceType, &ulCharacteristics)) 376 { 377 if ((ulCharacteristics & FILE_FLOPPY_DISKETTE) == FILE_FLOPPY_DISKETTE) 378 ret = TRUE; 379 } 380 381 CloseHandle(hDevice); 382 383 return ret; 384 } 385 386 BOOL IsDriveFloppyA(LPCSTR pszDriveRoot) 387 { 388 WCHAR szRoot[8]; 389 MultiByteToWideChar(CP_ACP, 0, pszDriveRoot, -1, szRoot, _countof(szRoot)); 390 return IsDriveFloppyW(szRoot); 391 } 392 393 VOID 394 CDrvDefExt::InitGeneralPage(HWND hwndDlg) 395 { 396 WCHAR wszVolumeName[MAX_PATH+1] = {0}; 397 WCHAR wszFileSystem[MAX_PATH+1] = {0}; 398 WCHAR wszBuf[128]; 399 BOOL bRet; 400 401 bRet = GetVolumeInformationW(m_wszDrive, wszVolumeName, _countof(wszVolumeName), NULL, NULL, NULL, wszFileSystem, _countof(wszFileSystem)); 402 if (bRet) 403 { 404 /* Set volume label and filesystem */ 405 SetDlgItemTextW(hwndDlg, 14000, wszVolumeName); 406 SetDlgItemTextW(hwndDlg, 14002, wszFileSystem); 407 } 408 else 409 { 410 LoadStringW(shell32_hInstance, IDS_FS_UNKNOWN, wszFileSystem, _countof(wszFileSystem)); 411 SetDlgItemTextW(hwndDlg, 14002, wszFileSystem); 412 } 413 414 /* Set drive type and icon */ 415 UINT DriveType = GetDriveTypeW(m_wszDrive); 416 UINT IconId, TypeStrId = 0; 417 switch (DriveType) 418 { 419 case DRIVE_REMOVABLE: 420 if (IsDriveFloppyW(m_wszDrive)) 421 IconId = IDI_SHELL_3_14_FLOPPY; 422 else 423 IconId = IDI_SHELL_REMOVEABLE; 424 break; 425 case DRIVE_CDROM: IconId = IDI_SHELL_CDROM; TypeStrId = IDS_DRIVE_CDROM; break; 426 case DRIVE_REMOTE: IconId = IDI_SHELL_NETDRIVE; TypeStrId = IDS_DRIVE_NETWORK; break; 427 case DRIVE_RAMDISK: IconId = IDI_SHELL_RAMDISK; break; 428 default: IconId = IDI_SHELL_DRIVE; TypeStrId = IDS_DRIVE_FIXED; 429 } 430 431 if (DriveType == DRIVE_CDROM || DriveType == DRIVE_REMOTE) 432 { 433 /* volume label textbox */ 434 SendMessage(GetDlgItem(hwndDlg, 14000), EM_SETREADONLY, TRUE, 0); 435 436 /* disk compression */ 437 ShowWindow(GetDlgItem(hwndDlg, 14011), FALSE); 438 439 /* index */ 440 ShowWindow(GetDlgItem(hwndDlg, 14012), FALSE); 441 } 442 443 HICON hIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IconId), IMAGE_ICON, 32, 32, LR_SHARED); 444 if (hIcon) 445 SendDlgItemMessageW(hwndDlg, 14016, STM_SETICON, (WPARAM)hIcon, 0); 446 if (TypeStrId && LoadStringW(shell32_hInstance, TypeStrId, wszBuf, _countof(wszBuf))) 447 SetDlgItemTextW(hwndDlg, 14001, wszBuf); 448 449 ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes; 450 if(GetDiskFreeSpaceExW(m_wszDrive, &FreeBytesAvailable, &TotalNumberOfBytes, NULL)) 451 { 452 /* Init free space percentage used for drawing piechart */ 453 m_FreeSpacePerc = (UINT)(FreeBytesAvailable.QuadPart * 100ull / TotalNumberOfBytes.QuadPart); 454 455 /* Used space */ 456 if (SH_FormatByteSize(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 457 SetDlgItemTextW(hwndDlg, 14003, wszBuf); 458 459 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 460 SetDlgItemTextW(hwndDlg, 14004, wszBuf); 461 462 /* Free space */ 463 if (SH_FormatByteSize(FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 464 SetDlgItemTextW(hwndDlg, 14005, wszBuf); 465 466 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 467 SetDlgItemTextW(hwndDlg, 14006, wszBuf); 468 469 /* Total space */ 470 if (SH_FormatByteSize(TotalNumberOfBytes.QuadPart, wszBuf, _countof(wszBuf))) 471 SetDlgItemTextW(hwndDlg, 14007, wszBuf); 472 473 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, wszBuf, _countof(wszBuf))) 474 SetDlgItemTextW(hwndDlg, 14008, wszBuf); 475 } 476 else 477 { 478 m_FreeSpacePerc = 0; 479 480 if (SH_FormatByteSize(0, wszBuf, _countof(wszBuf))) 481 { 482 SetDlgItemTextW(hwndDlg, 14003, wszBuf); 483 SetDlgItemTextW(hwndDlg, 14005, wszBuf); 484 SetDlgItemTextW(hwndDlg, 14007, wszBuf); 485 } 486 if (StrFormatByteSizeW(0, wszBuf, _countof(wszBuf))) 487 { 488 SetDlgItemTextW(hwndDlg, 14004, wszBuf); 489 SetDlgItemTextW(hwndDlg, 14006, wszBuf); 490 SetDlgItemTextW(hwndDlg, 14008, wszBuf); 491 } 492 } 493 494 /* Set drive description */ 495 WCHAR wszFormat[50]; 496 GetDlgItemTextW(hwndDlg, 14009, wszFormat, _countof(wszFormat)); 497 swprintf(wszBuf, wszFormat, m_wszDrive[0]); 498 SetDlgItemTextW(hwndDlg, 14009, wszBuf); 499 500 /* show disk cleanup button only for fixed drives */ 501 ShowWindow(GetDlgItem(hwndDlg, 14010), DriveType == DRIVE_FIXED); 502 } 503 504 INT_PTR CALLBACK 505 CDrvDefExt::GeneralPageProc( 506 HWND hwndDlg, 507 UINT uMsg, 508 WPARAM wParam, 509 LPARAM lParam) 510 { 511 switch(uMsg) 512 { 513 case WM_INITDIALOG: 514 { 515 LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam; 516 if (ppsp == NULL) 517 break; 518 519 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(ppsp->lParam); 520 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pDrvDefExt); 521 pDrvDefExt->InitGeneralPage(hwndDlg); 522 return TRUE; 523 } 524 case WM_DRAWITEM: 525 { 526 LPDRAWITEMSTRUCT pDrawItem = (LPDRAWITEMSTRUCT)lParam; 527 528 if (pDrawItem->CtlID >= 14013 && pDrawItem->CtlID <= 14015) 529 { 530 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 531 pDrvDefExt->PaintStaticControls(hwndDlg, pDrawItem); 532 return TRUE; 533 } 534 break; 535 } 536 case WM_PAINT: 537 break; 538 case WM_COMMAND: 539 if (LOWORD(wParam) == 14010) /* Disk Cleanup */ 540 { 541 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 542 WCHAR wszBuf[256]; 543 DWORD cbBuf = sizeof(wszBuf); 544 545 if (RegGetValueW(HKEY_LOCAL_MACHINE, 546 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\CleanupPath", 547 NULL, 548 RRF_RT_REG_SZ, 549 NULL, 550 (PVOID)wszBuf, 551 &cbBuf) == ERROR_SUCCESS) 552 { 553 WCHAR wszCmd[MAX_PATH]; 554 555 StringCbPrintfW(wszCmd, sizeof(wszCmd), wszBuf, pDrvDefExt->m_wszDrive[0]); 556 557 if (ShellExecuteW(hwndDlg, NULL, wszCmd, NULL, NULL, SW_SHOW) <= (HINSTANCE)32) 558 ERR("Failed to create cleanup process %ls\n", wszCmd); 559 } 560 } 561 else if (LOWORD(wParam) == 14000) /* Label */ 562 { 563 if (HIWORD(wParam) == EN_CHANGE) 564 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 565 } 566 break; 567 case WM_NOTIFY: 568 if (((LPNMHDR)lParam)->hwndFrom == GetParent(hwndDlg)) 569 { 570 /* Property Sheet */ 571 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam; 572 573 if (lppsn->hdr.code == PSN_APPLY) 574 { 575 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 576 WCHAR wszBuf[256]; 577 578 if (GetDlgItemTextW(hwndDlg, 14000, wszBuf, _countof(wszBuf))) 579 SetVolumeLabelW(pDrvDefExt->m_wszDrive, wszBuf); 580 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); 581 return TRUE; 582 } 583 } 584 break; 585 586 default: 587 break; 588 } 589 590 return FALSE; 591 } 592 593 INT_PTR CALLBACK 594 CDrvDefExt::ExtraPageProc( 595 HWND hwndDlg, 596 UINT uMsg, 597 WPARAM wParam, 598 LPARAM lParam) 599 { 600 switch (uMsg) 601 { 602 case WM_INITDIALOG: 603 { 604 LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam; 605 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam); 606 return TRUE; 607 } 608 case WM_COMMAND: 609 { 610 WCHAR wszBuf[MAX_PATH]; 611 DWORD cbBuf = sizeof(wszBuf); 612 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 613 614 switch(LOWORD(wParam)) 615 { 616 case 14000: 617 DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_CHECK_DISK), hwndDlg, ChkDskDlg, (LPARAM)pDrvDefExt->m_wszDrive); 618 break; 619 case 14001: 620 if (RegGetValueW(HKEY_LOCAL_MACHINE, 621 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath", 622 NULL, 623 RRF_RT_REG_SZ, 624 NULL, 625 (PVOID)wszBuf, 626 &cbBuf) == ERROR_SUCCESS) 627 { 628 WCHAR wszCmd[MAX_PATH]; 629 630 StringCbPrintfW(wszCmd, sizeof(wszCmd), wszBuf, pDrvDefExt->m_wszDrive[0]); 631 632 if (ShellExecuteW(hwndDlg, NULL, wszCmd, NULL, NULL, SW_SHOW) <= (HINSTANCE)32) 633 ERR("Failed to create defrag process %ls\n", wszCmd); 634 } 635 break; 636 case 14002: 637 if (RegGetValueW(HKEY_LOCAL_MACHINE, 638 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath", 639 NULL, 640 RRF_RT_REG_SZ, 641 NULL, 642 (PVOID)wszBuf, 643 &cbBuf) == ERROR_SUCCESS) 644 { 645 if (ShellExecuteW(hwndDlg, NULL, wszBuf, NULL, NULL, SW_SHOW) <= (HINSTANCE)32) 646 ERR("Failed to create backup process %ls\n", wszBuf); 647 } 648 } 649 break; 650 } 651 } 652 return FALSE; 653 } 654 655 INT_PTR CALLBACK 656 CDrvDefExt::HardwarePageProc( 657 HWND hwndDlg, 658 UINT uMsg, 659 WPARAM wParam, 660 LPARAM lParam) 661 { 662 UNREFERENCED_PARAMETER(lParam); 663 UNREFERENCED_PARAMETER(wParam); 664 665 switch(uMsg) 666 { 667 case WM_INITDIALOG: 668 { 669 GUID Guids[2]; 670 Guids[0] = GUID_DEVCLASS_DISKDRIVE; 671 Guids[1] = GUID_DEVCLASS_CDROM; 672 673 /* create the hardware page */ 674 DeviceCreateHardwarePageEx(hwndDlg, Guids, _countof(Guids), HWPD_STANDARDLIST); 675 break; 676 } 677 } 678 679 return FALSE; 680 } 681 682 CDrvDefExt::CDrvDefExt() 683 { 684 m_wszDrive[0] = L'\0'; 685 } 686 687 CDrvDefExt::~CDrvDefExt() 688 { 689 690 } 691 692 HRESULT WINAPI 693 CDrvDefExt::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pDataObj, HKEY hkeyProgID) 694 { 695 FORMATETC format; 696 STGMEDIUM stgm; 697 HRESULT hr; 698 699 TRACE("%p %p %p %p\n", this, pidlFolder, pDataObj, hkeyProgID); 700 701 if (!pDataObj) 702 return E_FAIL; 703 704 format.cfFormat = CF_HDROP; 705 format.ptd = NULL; 706 format.dwAspect = DVASPECT_CONTENT; 707 format.lindex = -1; 708 format.tymed = TYMED_HGLOBAL; 709 710 hr = pDataObj->GetData(&format, &stgm); 711 if (FAILED(hr)) 712 return hr; 713 714 if (!DragQueryFileW((HDROP)stgm.hGlobal, 0, m_wszDrive, _countof(m_wszDrive))) 715 { 716 ERR("DragQueryFileW failed\n"); 717 ReleaseStgMedium(&stgm); 718 return E_FAIL; 719 } 720 721 ReleaseStgMedium(&stgm); 722 TRACE("Drive properties %ls\n", m_wszDrive); 723 724 return S_OK; 725 } 726 727 HRESULT WINAPI 728 CDrvDefExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) 729 { 730 UNIMPLEMENTED; 731 return E_NOTIMPL; 732 } 733 734 HRESULT WINAPI 735 CDrvDefExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) 736 { 737 UNIMPLEMENTED; 738 return E_NOTIMPL; 739 } 740 741 HRESULT WINAPI 742 CDrvDefExt::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax) 743 { 744 UNIMPLEMENTED; 745 return E_NOTIMPL; 746 } 747 748 HRESULT WINAPI 749 CDrvDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) 750 { 751 HPROPSHEETPAGE hPage; 752 753 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_PROPERTIES, 754 GeneralPageProc, 755 (LPARAM)this, 756 NULL); 757 if (hPage) 758 pfnAddPage(hPage, lParam); 759 760 if (GetDriveTypeW(m_wszDrive) == DRIVE_FIXED) 761 { 762 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_TOOLS, 763 ExtraPageProc, 764 (LPARAM)this, 765 NULL); 766 if (hPage) 767 pfnAddPage(hPage, lParam); 768 } 769 770 if (GetDriveTypeW(m_wszDrive) != DRIVE_REMOTE) 771 { 772 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_HARDWARE, 773 HardwarePageProc, 774 (LPARAM)this, 775 NULL); 776 if (hPage) 777 pfnAddPage(hPage, lParam); 778 } 779 780 return S_OK; 781 } 782 783 HRESULT WINAPI 784 CDrvDefExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam) 785 { 786 UNIMPLEMENTED; 787 return E_NOTIMPL; 788 } 789 790 HRESULT WINAPI 791 CDrvDefExt::SetSite(IUnknown *punk) 792 { 793 UNIMPLEMENTED; 794 return E_NOTIMPL; 795 } 796 797 HRESULT WINAPI 798 CDrvDefExt::GetSite(REFIID iid, void **ppvSite) 799 { 800 UNIMPLEMENTED; 801 return E_NOTIMPL; 802 } 803