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 hDarkBluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 128)); 220 HPEN hDarkMagPen = CreatePen(PS_SOLID, 1, RGB(128, 0, 128)); 221 HPEN hOldPen = (HPEN)SelectObject(pDrawItem->hDC, hDarkMagPen); 222 INT xCenter = (pDrawItem->rcItem.left + pDrawItem->rcItem.right) / 2; 223 INT yCenter = (pDrawItem->rcItem.top + pDrawItem->rcItem.bottom - 10) / 2; 224 INT cx = pDrawItem->rcItem.right - pDrawItem->rcItem.left; 225 INT cy = pDrawItem->rcItem.bottom - pDrawItem->rcItem.top - 10; 226 INT xRadial = xCenter + (INT)(cos(M_PI + m_FreeSpacePerc / 100.0f * M_PI * 2.0f) * cx / 2); 227 INT yRadial = yCenter - (INT)(sin(M_PI + m_FreeSpacePerc / 100.0f * M_PI * 2.0f) * cy / 2); 228 229 TRACE("FreeSpace %u a %f cx %d\n", m_FreeSpacePerc, M_PI+m_FreeSpacePerc / 100.0f * M_PI * 2.0f, cx); 230 231 for (INT x = pDrawItem->rcItem.left; x < pDrawItem->rcItem.right; ++x) 232 { 233 double cos_val = (x - xCenter) * 2.0f / cx; 234 INT y = yCenter + (INT)(sin(acos(cos_val)) * cy / 2) - 1; 235 236 if (m_FreeSpacePerc < 50 && x == xRadial) 237 SelectObject(pDrawItem->hDC, hDarkBluePen); 238 239 MoveToEx(pDrawItem->hDC, x, y, NULL); 240 LineTo(pDrawItem->hDC, x, y + 10); 241 } 242 243 SelectObject(pDrawItem->hDC, hOldPen); 244 245 if (m_FreeSpacePerc > 50) 246 { 247 hbrOld = (HBRUSH)SelectObject(pDrawItem->hDC, hMagBrush); 248 249 Ellipse(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, 250 pDrawItem->rcItem.right, pDrawItem->rcItem.bottom - 10); 251 252 SelectObject(pDrawItem->hDC, hBlueBrush); 253 254 if (m_FreeSpacePerc < 100) 255 { 256 Pie(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, pDrawItem->rcItem.right, 257 pDrawItem->rcItem.bottom - 10, xRadial, yRadial, pDrawItem->rcItem.left, yCenter); 258 } 259 } 260 else 261 { 262 hbrOld = (HBRUSH)SelectObject(pDrawItem->hDC, hBlueBrush); 263 264 Ellipse(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, 265 pDrawItem->rcItem.right, pDrawItem->rcItem.bottom - 10); 266 267 SelectObject(pDrawItem->hDC, hMagBrush); 268 269 if (m_FreeSpacePerc > 0) 270 { 271 Pie(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, pDrawItem->rcItem.right, 272 pDrawItem->rcItem.bottom - 10, pDrawItem->rcItem.left, yCenter, xRadial, yRadial); 273 } 274 } 275 276 SelectObject(pDrawItem->hDC, hbrOld); 277 278 DeleteObject(hBlueBrush); 279 DeleteObject(hMagBrush); 280 DeleteObject(hDarkBluePen); 281 DeleteObject(hDarkMagPen); 282 } 283 } 284 285 // https://stackoverflow.com/questions/3098696/get-information-about-disk-drives-result-on-windows7-32-bit-system/3100268#3100268 286 static BOOL 287 GetDriveTypeAndCharacteristics(HANDLE hDevice, DEVICE_TYPE *pDeviceType, ULONG *pCharacteristics) 288 { 289 NTSTATUS Status; 290 IO_STATUS_BLOCK IoStatusBlock; 291 FILE_FS_DEVICE_INFORMATION DeviceInfo; 292 293 Status = NtQueryVolumeInformationFile(hDevice, &IoStatusBlock, 294 &DeviceInfo, sizeof(DeviceInfo), 295 FileFsDeviceInformation); 296 if (Status == NO_ERROR) 297 { 298 *pDeviceType = DeviceInfo.DeviceType; 299 *pCharacteristics = DeviceInfo.Characteristics; 300 return TRUE; 301 } 302 303 return FALSE; 304 } 305 306 BOOL IsDriveFloppyW(LPCWSTR pszDriveRoot) 307 { 308 LPCWSTR RootPath = pszDriveRoot; 309 WCHAR szRoot[16], szDeviceName[16]; 310 UINT uType; 311 HANDLE hDevice; 312 DEVICE_TYPE DeviceType; 313 ULONG ulCharacteristics; 314 BOOL ret; 315 316 lstrcpynW(szRoot, RootPath, _countof(szRoot)); 317 318 if (L'a' <= szRoot[0] && szRoot[0] <= 'z') 319 { 320 szRoot[0] += ('A' - 'a'); 321 } 322 323 if ('A' <= szRoot[0] && szRoot[0] <= L'Z' && 324 szRoot[1] == L':' && szRoot[2] == 0) 325 { 326 // 'C:' --> 'C:\' 327 szRoot[2] = L'\\'; 328 szRoot[3] = 0; 329 } 330 331 if (!PathIsRootW(szRoot)) 332 { 333 return FALSE; 334 } 335 336 uType = GetDriveTypeW(szRoot); 337 if (uType == DRIVE_REMOVABLE) 338 { 339 if (szRoot[0] == L'A' || szRoot[0] == L'B') 340 return TRUE; 341 } 342 else 343 { 344 return FALSE; 345 } 346 347 lstrcpynW(szDeviceName, L"\\\\.\\", _countof(szDeviceName)); 348 szDeviceName[4] = szRoot[0]; 349 szDeviceName[5] = L':'; 350 szDeviceName[6] = UNICODE_NULL; 351 352 hDevice = CreateFileW(szDeviceName, FILE_READ_ATTRIBUTES, 353 FILE_SHARE_READ | FILE_SHARE_WRITE, 354 NULL, OPEN_EXISTING, 0, NULL); 355 if (hDevice == INVALID_HANDLE_VALUE) 356 { 357 return FALSE; 358 } 359 360 ret = FALSE; 361 if (GetDriveTypeAndCharacteristics(hDevice, &DeviceType, &ulCharacteristics)) 362 { 363 if ((ulCharacteristics & FILE_FLOPPY_DISKETTE) == FILE_FLOPPY_DISKETTE) 364 ret = TRUE; 365 } 366 367 CloseHandle(hDevice); 368 369 return ret; 370 } 371 372 BOOL IsDriveFloppyA(LPCSTR pszDriveRoot) 373 { 374 WCHAR szRoot[8]; 375 MultiByteToWideChar(CP_ACP, 0, pszDriveRoot, -1, szRoot, _countof(szRoot)); 376 return IsDriveFloppyW(szRoot); 377 } 378 379 VOID 380 CDrvDefExt::InitGeneralPage(HWND hwndDlg) 381 { 382 WCHAR wszVolumeName[MAX_PATH+1] = {0}; 383 WCHAR wszFileSystem[MAX_PATH+1] = {0}; 384 WCHAR wszBuf[128]; 385 BOOL bRet; 386 387 bRet = GetVolumeInformationW(m_wszDrive, wszVolumeName, _countof(wszVolumeName), NULL, NULL, NULL, wszFileSystem, _countof(wszFileSystem)); 388 if (bRet) 389 { 390 /* Set volume label and filesystem */ 391 SetDlgItemTextW(hwndDlg, 14000, wszVolumeName); 392 SetDlgItemTextW(hwndDlg, 14002, wszFileSystem); 393 } 394 else 395 { 396 LoadStringW(shell32_hInstance, IDS_FS_UNKNOWN, wszFileSystem, _countof(wszFileSystem)); 397 SetDlgItemTextW(hwndDlg, 14002, wszFileSystem); 398 } 399 400 /* Set drive type and icon */ 401 UINT DriveType = GetDriveTypeW(m_wszDrive); 402 UINT IconId, TypeStrId = 0; 403 switch (DriveType) 404 { 405 case DRIVE_REMOVABLE: 406 if (IsDriveFloppyW(m_wszDrive)) 407 IconId = IDI_SHELL_3_14_FLOPPY; 408 else 409 IconId = IDI_SHELL_REMOVEABLE; 410 break; 411 case DRIVE_CDROM: IconId = IDI_SHELL_CDROM; TypeStrId = IDS_DRIVE_CDROM; break; 412 case DRIVE_REMOTE: IconId = IDI_SHELL_NETDRIVE; TypeStrId = IDS_DRIVE_NETWORK; break; 413 case DRIVE_RAMDISK: IconId = IDI_SHELL_RAMDISK; break; 414 default: IconId = IDI_SHELL_DRIVE; TypeStrId = IDS_DRIVE_FIXED; 415 } 416 417 if (DriveType == DRIVE_CDROM || DriveType == DRIVE_REMOTE) 418 { 419 /* volume label textbox */ 420 SendMessage(GetDlgItem(hwndDlg, 14000), EM_SETREADONLY, TRUE, 0); 421 422 /* disk compression */ 423 ShowWindow(GetDlgItem(hwndDlg, 14011), FALSE); 424 425 /* index */ 426 ShowWindow(GetDlgItem(hwndDlg, 14012), FALSE); 427 } 428 429 HICON hIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IconId), IMAGE_ICON, 32, 32, LR_SHARED); 430 if (hIcon) 431 SendDlgItemMessageW(hwndDlg, 14016, STM_SETICON, (WPARAM)hIcon, 0); 432 if (TypeStrId && LoadStringW(shell32_hInstance, TypeStrId, wszBuf, _countof(wszBuf))) 433 SetDlgItemTextW(hwndDlg, 14001, wszBuf); 434 435 ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes; 436 if(GetDiskFreeSpaceExW(m_wszDrive, &FreeBytesAvailable, &TotalNumberOfBytes, NULL)) 437 { 438 /* Init free space percentage used for drawing piechart */ 439 m_FreeSpacePerc = (UINT)(FreeBytesAvailable.QuadPart * 100ull / TotalNumberOfBytes.QuadPart); 440 441 /* Used space */ 442 if (SH_FormatByteSize(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 443 SetDlgItemTextW(hwndDlg, 14003, wszBuf); 444 445 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 446 SetDlgItemTextW(hwndDlg, 14004, wszBuf); 447 448 /* Free space */ 449 if (SH_FormatByteSize(FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 450 SetDlgItemTextW(hwndDlg, 14005, wszBuf); 451 452 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf))) 453 SetDlgItemTextW(hwndDlg, 14006, wszBuf); 454 455 /* Total space */ 456 if (SH_FormatByteSize(TotalNumberOfBytes.QuadPart, wszBuf, _countof(wszBuf))) 457 SetDlgItemTextW(hwndDlg, 14007, wszBuf); 458 459 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, wszBuf, _countof(wszBuf))) 460 SetDlgItemTextW(hwndDlg, 14008, wszBuf); 461 } 462 else 463 { 464 m_FreeSpacePerc = 0; 465 466 if (SH_FormatByteSize(0, wszBuf, _countof(wszBuf))) 467 { 468 SetDlgItemTextW(hwndDlg, 14003, wszBuf); 469 SetDlgItemTextW(hwndDlg, 14005, wszBuf); 470 SetDlgItemTextW(hwndDlg, 14007, wszBuf); 471 } 472 if (StrFormatByteSizeW(0, wszBuf, _countof(wszBuf))) 473 { 474 SetDlgItemTextW(hwndDlg, 14004, wszBuf); 475 SetDlgItemTextW(hwndDlg, 14006, wszBuf); 476 SetDlgItemTextW(hwndDlg, 14008, wszBuf); 477 } 478 } 479 480 /* Set drive description */ 481 WCHAR wszFormat[50]; 482 GetDlgItemTextW(hwndDlg, 14009, wszFormat, _countof(wszFormat)); 483 swprintf(wszBuf, wszFormat, m_wszDrive[0]); 484 SetDlgItemTextW(hwndDlg, 14009, wszBuf); 485 486 /* show disk cleanup button only for fixed drives */ 487 ShowWindow(GetDlgItem(hwndDlg, 14010), DriveType == DRIVE_FIXED); 488 } 489 490 INT_PTR CALLBACK 491 CDrvDefExt::GeneralPageProc( 492 HWND hwndDlg, 493 UINT uMsg, 494 WPARAM wParam, 495 LPARAM lParam) 496 { 497 switch(uMsg) 498 { 499 case WM_INITDIALOG: 500 { 501 LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam; 502 if (ppsp == NULL) 503 break; 504 505 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(ppsp->lParam); 506 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pDrvDefExt); 507 pDrvDefExt->InitGeneralPage(hwndDlg); 508 return TRUE; 509 } 510 case WM_DRAWITEM: 511 { 512 LPDRAWITEMSTRUCT pDrawItem = (LPDRAWITEMSTRUCT)lParam; 513 514 if (pDrawItem->CtlID >= 14013 && pDrawItem->CtlID <= 14015) 515 { 516 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 517 pDrvDefExt->PaintStaticControls(hwndDlg, pDrawItem); 518 return TRUE; 519 } 520 break; 521 } 522 case WM_PAINT: 523 break; 524 case WM_COMMAND: 525 if (LOWORD(wParam) == 14010) /* Disk Cleanup */ 526 { 527 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 528 WCHAR wszBuf[256]; 529 DWORD cbBuf = sizeof(wszBuf); 530 531 if (RegGetValueW(HKEY_LOCAL_MACHINE, 532 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\CleanupPath", 533 NULL, 534 RRF_RT_REG_SZ, 535 NULL, 536 (PVOID)wszBuf, 537 &cbBuf) == ERROR_SUCCESS) 538 { 539 WCHAR wszCmd[MAX_PATH]; 540 541 StringCbPrintfW(wszCmd, sizeof(wszCmd), wszBuf, pDrvDefExt->m_wszDrive[0]); 542 543 if (ShellExecuteW(hwndDlg, NULL, wszCmd, NULL, NULL, SW_SHOW) <= (HINSTANCE)32) 544 ERR("Failed to create cleanup process %ls\n", wszCmd); 545 } 546 } 547 else if (LOWORD(wParam) == 14000) /* Label */ 548 { 549 if (HIWORD(wParam) == EN_CHANGE) 550 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 551 } 552 break; 553 case WM_NOTIFY: 554 if (((LPNMHDR)lParam)->hwndFrom == GetParent(hwndDlg)) 555 { 556 /* Property Sheet */ 557 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam; 558 559 if (lppsn->hdr.code == PSN_APPLY) 560 { 561 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 562 WCHAR wszBuf[256]; 563 564 if (GetDlgItemTextW(hwndDlg, 14000, wszBuf, _countof(wszBuf))) 565 SetVolumeLabelW(pDrvDefExt->m_wszDrive, wszBuf); 566 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); 567 return TRUE; 568 } 569 } 570 break; 571 572 default: 573 break; 574 } 575 576 return FALSE; 577 } 578 579 INT_PTR CALLBACK 580 CDrvDefExt::ExtraPageProc( 581 HWND hwndDlg, 582 UINT uMsg, 583 WPARAM wParam, 584 LPARAM lParam) 585 { 586 switch (uMsg) 587 { 588 case WM_INITDIALOG: 589 { 590 LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam; 591 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam); 592 return TRUE; 593 } 594 case WM_COMMAND: 595 { 596 WCHAR wszBuf[MAX_PATH]; 597 DWORD cbBuf = sizeof(wszBuf); 598 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); 599 600 switch(LOWORD(wParam)) 601 { 602 case 14000: 603 DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_CHECK_DISK), hwndDlg, ChkDskDlg, (LPARAM)pDrvDefExt->m_wszDrive); 604 break; 605 case 14001: 606 if (RegGetValueW(HKEY_LOCAL_MACHINE, 607 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath", 608 NULL, 609 RRF_RT_REG_SZ, 610 NULL, 611 (PVOID)wszBuf, 612 &cbBuf) == ERROR_SUCCESS) 613 { 614 WCHAR wszCmd[MAX_PATH]; 615 616 StringCbPrintfW(wszCmd, sizeof(wszCmd), wszBuf, pDrvDefExt->m_wszDrive[0]); 617 618 if (ShellExecuteW(hwndDlg, NULL, wszCmd, NULL, NULL, SW_SHOW) <= (HINSTANCE)32) 619 ERR("Failed to create defrag process %ls\n", wszCmd); 620 } 621 break; 622 case 14002: 623 if (RegGetValueW(HKEY_LOCAL_MACHINE, 624 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath", 625 NULL, 626 RRF_RT_REG_SZ, 627 NULL, 628 (PVOID)wszBuf, 629 &cbBuf) == ERROR_SUCCESS) 630 { 631 if (ShellExecuteW(hwndDlg, NULL, wszBuf, NULL, NULL, SW_SHOW) <= (HINSTANCE)32) 632 ERR("Failed to create backup process %ls\n", wszBuf); 633 } 634 } 635 break; 636 } 637 } 638 return FALSE; 639 } 640 641 INT_PTR CALLBACK 642 CDrvDefExt::HardwarePageProc( 643 HWND hwndDlg, 644 UINT uMsg, 645 WPARAM wParam, 646 LPARAM lParam) 647 { 648 UNREFERENCED_PARAMETER(lParam); 649 UNREFERENCED_PARAMETER(wParam); 650 651 switch(uMsg) 652 { 653 case WM_INITDIALOG: 654 { 655 GUID Guids[2]; 656 Guids[0] = GUID_DEVCLASS_DISKDRIVE; 657 Guids[1] = GUID_DEVCLASS_CDROM; 658 659 /* create the hardware page */ 660 DeviceCreateHardwarePageEx(hwndDlg, Guids, _countof(Guids), HWPD_STANDARDLIST); 661 break; 662 } 663 } 664 665 return FALSE; 666 } 667 668 CDrvDefExt::CDrvDefExt() 669 { 670 m_wszDrive[0] = L'\0'; 671 } 672 673 CDrvDefExt::~CDrvDefExt() 674 { 675 676 } 677 678 HRESULT WINAPI 679 CDrvDefExt::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pDataObj, HKEY hkeyProgID) 680 { 681 FORMATETC format; 682 STGMEDIUM stgm; 683 HRESULT hr; 684 685 TRACE("%p %p %p %p\n", this, pidlFolder, pDataObj, hkeyProgID); 686 687 if (!pDataObj) 688 return E_FAIL; 689 690 format.cfFormat = CF_HDROP; 691 format.ptd = NULL; 692 format.dwAspect = DVASPECT_CONTENT; 693 format.lindex = -1; 694 format.tymed = TYMED_HGLOBAL; 695 696 hr = pDataObj->GetData(&format, &stgm); 697 if (FAILED(hr)) 698 return hr; 699 700 if (!DragQueryFileW((HDROP)stgm.hGlobal, 0, m_wszDrive, _countof(m_wszDrive))) 701 { 702 ERR("DragQueryFileW failed\n"); 703 ReleaseStgMedium(&stgm); 704 return E_FAIL; 705 } 706 707 ReleaseStgMedium(&stgm); 708 TRACE("Drive properties %ls\n", m_wszDrive); 709 710 return S_OK; 711 } 712 713 HRESULT WINAPI 714 CDrvDefExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) 715 { 716 UNIMPLEMENTED; 717 return E_NOTIMPL; 718 } 719 720 HRESULT WINAPI 721 CDrvDefExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) 722 { 723 UNIMPLEMENTED; 724 return E_NOTIMPL; 725 } 726 727 HRESULT WINAPI 728 CDrvDefExt::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax) 729 { 730 UNIMPLEMENTED; 731 return E_NOTIMPL; 732 } 733 734 HRESULT WINAPI 735 CDrvDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) 736 { 737 HPROPSHEETPAGE hPage; 738 739 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_PROPERTIES, 740 GeneralPageProc, 741 (LPARAM)this, 742 NULL); 743 if (hPage) 744 pfnAddPage(hPage, lParam); 745 746 if (GetDriveTypeW(m_wszDrive) == DRIVE_FIXED) 747 { 748 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_TOOLS, 749 ExtraPageProc, 750 (LPARAM)this, 751 NULL); 752 if (hPage) 753 pfnAddPage(hPage, lParam); 754 } 755 756 if (GetDriveTypeW(m_wszDrive) != DRIVE_REMOTE) 757 { 758 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_HARDWARE, 759 HardwarePageProc, 760 (LPARAM)this, 761 NULL); 762 if (hPage) 763 pfnAddPage(hPage, lParam); 764 } 765 766 return S_OK; 767 } 768 769 HRESULT WINAPI 770 CDrvDefExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam) 771 { 772 UNIMPLEMENTED; 773 return E_NOTIMPL; 774 } 775 776 HRESULT WINAPI 777 CDrvDefExt::SetSite(IUnknown *punk) 778 { 779 UNIMPLEMENTED; 780 return E_NOTIMPL; 781 } 782 783 HRESULT WINAPI 784 CDrvDefExt::GetSite(REFIID iid, void **ppvSite) 785 { 786 UNIMPLEMENTED; 787 return E_NOTIMPL; 788 } 789