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
GetDriveNameWithLetter(LPWSTR pwszText,UINT cchTextMax,LPCWSTR pwszDrive)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
InitializeChkDskDialog(HWND hwndDlg,LPCWSTR pwszDrive)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
ChkdskCallback(IN CALLBACKCOMMAND Command,IN ULONG SubAction,IN PVOID ActionInfo)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
ChkDskNow(HWND hwndDlg,LPCWSTR pwszDrive)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
ChkDskDlg(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
PaintStaticControls(HWND hwndDlg,LPDRAWITEMSTRUCT pDrawItem)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
GetDriveTypeAndCharacteristics(HANDLE hDevice,DEVICE_TYPE * pDeviceType,ULONG * pCharacteristics)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
IsDriveFloppyW(LPCWSTR pszDriveRoot)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
IsDriveFloppyA(LPCSTR pszDriveRoot)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
InitGeneralPage(HWND hwndDlg)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
GeneralPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
ExtraPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
HardwarePageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
CDrvDefExt()682 CDrvDefExt::CDrvDefExt()
683 {
684 m_wszDrive[0] = L'\0';
685 }
686
~CDrvDefExt()687 CDrvDefExt::~CDrvDefExt()
688 {
689
690 }
691
692 HRESULT WINAPI
Initialize(PCIDLIST_ABSOLUTE pidlFolder,IDataObject * pDataObj,HKEY hkeyProgID)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
QueryContextMenu(HMENU hmenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)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
InvokeCommand(LPCMINVOKECOMMANDINFO lpici)735 CDrvDefExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
736 {
737 UNIMPLEMENTED;
738 return E_NOTIMPL;
739 }
740
741 HRESULT WINAPI
GetCommandString(UINT_PTR idCmd,UINT uType,UINT * pwReserved,LPSTR pszName,UINT cchMax)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
AddPages(LPFNADDPROPSHEETPAGE pfnAddPage,LPARAM lParam)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
ReplacePage(UINT uPageID,LPFNADDPROPSHEETPAGE pfnReplacePage,LPARAM lParam)784 CDrvDefExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam)
785 {
786 UNIMPLEMENTED;
787 return E_NOTIMPL;
788 }
789
790 HRESULT WINAPI
SetSite(IUnknown * punk)791 CDrvDefExt::SetSite(IUnknown *punk)
792 {
793 UNIMPLEMENTED;
794 return E_NOTIMPL;
795 }
796
797 HRESULT WINAPI
GetSite(REFIID iid,void ** ppvSite)798 CDrvDefExt::GetSite(REFIID iid, void **ppvSite)
799 {
800 UNIMPLEMENTED;
801 return E_NOTIMPL;
802 }
803