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