[shell32]
[reactos.git] / reactos / dll / win32 / shell32 / drvdefext.cpp
1 /*
2 * Provides default drive shell extension
3 *
4 * Copyright 2005 Johannes Anderwald
5 * Copyright 2012 Rafal Harabien
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 St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "precomp.h"
23
24 #define _USE_MATH_DEFINES
25 #include <math.h>
26
27 WINE_DEFAULT_DEBUG_CHANNEL(shell);
28
29 static const GUID GUID_DEVCLASS_DISKDRIVE = {0x4d36e967L, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
30
31 typedef enum
32 {
33 HWPD_STANDARDLIST = 0,
34 HWPD_LARGELIST,
35 HWPD_MAX = HWPD_LARGELIST
36 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
37
38 EXTERN_C HWND WINAPI
39 DeviceCreateHardwarePageEx(HWND hWndParent,
40 LPGUID lpGuids,
41 UINT uNumberOfGuids,
42 HWPAGE_DISPLAYMODE DisplayMode);
43 UINT SH_FormatByteSize(LONGLONG cbSize, LPWSTR pwszResult, UINT cchResultMax);
44
45 static VOID
46 GetDriveNameWithLetter(LPWSTR pwszText, UINT cchTextMax, LPCWSTR pwszDrive)
47 {
48 DWORD dwMaxComp, dwFileSys;
49 SIZE_T cchText = 0;
50
51 if (GetVolumeInformationW(pwszDrive, pwszText, cchTextMax, NULL, &dwMaxComp, &dwFileSys, NULL, 0))
52 {
53 cchText = wcslen(pwszText);
54 if (cchText == 0)
55 {
56 /* load default volume label */
57 cchText = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, pwszText, cchTextMax);
58 }
59 }
60
61 StringCchPrintfW(pwszText + cchText, cchTextMax - cchText, L" (%c)", pwszDrive[0]);
62 }
63
64 static VOID
65 InitializeChkDskDialog(HWND hwndDlg, LPCWSTR pwszDrive)
66 {
67 WCHAR wszText[100];
68 UINT Length;
69 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pwszDrive);
70
71 Length = GetWindowTextW(hwndDlg, wszText, sizeof(wszText) / sizeof(WCHAR));
72 wszText[Length] = L' ';
73 GetDriveNameWithLetter(&wszText[Length + 1], (sizeof(wszText) / sizeof(WCHAR)) - Length - 1, pwszDrive);
74 SetWindowText(hwndDlg, wszText);
75 }
76
77 static HWND hChkdskDrvDialog = NULL;
78 static BOOLEAN bChkdskSuccess = FALSE;
79
80 static BOOLEAN NTAPI
81 ChkdskCallback(
82 IN CALLBACKCOMMAND Command,
83 IN ULONG SubAction,
84 IN PVOID ActionInfo)
85 {
86 PDWORD Progress;
87 PBOOLEAN pSuccess;
88 switch(Command)
89 {
90 case PROGRESS:
91 Progress = (PDWORD)ActionInfo;
92 SendDlgItemMessageW(hChkdskDrvDialog, 14002, PBM_SETPOS, (WPARAM)*Progress, 0);
93 break;
94 case DONE:
95 pSuccess = (PBOOLEAN)ActionInfo;
96 bChkdskSuccess = (*pSuccess);
97 break;
98
99 case VOLUMEINUSE:
100 case INSUFFICIENTRIGHTS:
101 case FSNOTSUPPORTED:
102 case CLUSTERSIZETOOSMALL:
103 bChkdskSuccess = FALSE;
104 FIXME("\n");
105 break;
106
107 default:
108 break;
109 }
110
111 return TRUE;
112 }
113
114 static VOID
115 ChkDskNow(HWND hwndDlg, LPCWSTR pwszDrive)
116 {
117 //DWORD ClusterSize = 0;
118 WCHAR wszFs[30];
119 ULARGE_INTEGER TotalNumberOfFreeBytes, FreeBytesAvailableUser;
120 BOOLEAN bCorrectErrors = FALSE, bScanDrive = FALSE;
121
122 if(!GetVolumeInformationW(pwszDrive, NULL, 0, NULL, NULL, NULL, wszFs, _countof(wszFs)))
123 {
124 FIXME("failed to get drive fs type\n");
125 return;
126 }
127
128 if (!GetDiskFreeSpaceExW(pwszDrive, &FreeBytesAvailableUser, &TotalNumberOfFreeBytes, NULL))
129 {
130 FIXME("failed to get drive space type\n");
131 return;
132 }
133
134 /*if (!GetDefaultClusterSize(wszFs, &ClusterSize, &TotalNumberOfFreeBytes))
135 {
136 FIXME("invalid cluster size\n");
137 return;
138 }*/
139
140 if (SendDlgItemMessageW(hwndDlg, 14000, BM_GETCHECK, 0, 0) == BST_CHECKED)
141 bCorrectErrors = TRUE;
142
143 if (SendDlgItemMessageW(hwndDlg, 14001, BM_GETCHECK, 0, 0) == BST_CHECKED)
144 bScanDrive = TRUE;
145
146 hChkdskDrvDialog = hwndDlg;
147 bChkdskSuccess = FALSE;
148 SendDlgItemMessageW(hwndDlg, 14002, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
149 Chkdsk((LPWSTR)pwszDrive, (LPWSTR)wszFs, bCorrectErrors, TRUE, FALSE, bScanDrive, NULL, NULL, ChkdskCallback); // FIXME: casts
150
151 hChkdskDrvDialog = NULL;
152 bChkdskSuccess = FALSE;
153 }
154
155 static INT_PTR CALLBACK
156 ChkDskDlg(
157 HWND hwndDlg,
158 UINT uMsg,
159 WPARAM wParam,
160 LPARAM lParam)
161 {
162 switch(uMsg)
163 {
164 case WM_INITDIALOG:
165 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
166 InitializeChkDskDialog(hwndDlg, (LPCWSTR)lParam);
167 return TRUE;
168 case WM_COMMAND:
169 switch(LOWORD(wParam))
170 {
171 case IDCANCEL:
172 EndDialog(hwndDlg, 0);
173 break;
174 case IDOK:
175 {
176 LPCWSTR pwszDrive = (LPCWSTR)GetWindowLongPtr(hwndDlg, DWLP_USER);
177 ChkDskNow(hwndDlg, pwszDrive);
178 break;
179 }
180 }
181 break;
182 }
183
184 return FALSE;
185 }
186
187 VOID
188 CDrvDefExt::PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT pDrawItem)
189 {
190 HBRUSH hBrush;
191
192 if (pDrawItem->CtlID == 14013)
193 {
194 hBrush = CreateSolidBrush(RGB(0, 0, 255));
195 if (hBrush)
196 {
197 FillRect(pDrawItem->hDC, &pDrawItem->rcItem, hBrush);
198 DeleteObject((HGDIOBJ)hBrush);
199 }
200 }
201 else if (pDrawItem->CtlID == 14014)
202 {
203 hBrush = CreateSolidBrush(RGB(255, 0, 255));
204 if (hBrush)
205 {
206 FillRect(pDrawItem->hDC, &pDrawItem->rcItem, hBrush);
207 DeleteObject((HGDIOBJ)hBrush);
208 }
209 }
210 else if (pDrawItem->CtlID == 14015)
211 {
212 HBRUSH hBlueBrush = CreateSolidBrush(RGB(0, 0, 255));
213 HBRUSH hMagBrush = CreateSolidBrush(RGB(255, 0, 255));
214 HPEN hDarkBluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 128));
215 HPEN hDarkMagPen = CreatePen(PS_SOLID, 1, RGB(128, 0, 128));
216
217 INT xCenter = (pDrawItem->rcItem.left + pDrawItem->rcItem.right)/2;
218 INT yCenter = (pDrawItem->rcItem.top + pDrawItem->rcItem.bottom - 10)/2;
219 INT cx = pDrawItem->rcItem.right - pDrawItem->rcItem.left;
220 INT cy = pDrawItem->rcItem.bottom - pDrawItem->rcItem.top - 10;
221 TRACE("FreeSpace %u a %f cx %d\n", m_FreeSpacePerc, M_PI+m_FreeSpacePerc/100.0f*M_PI*2.0f, cx);
222
223 HBRUSH hbrOld = (HBRUSH)SelectObject(pDrawItem->hDC, hMagBrush);
224 INT xRadial = xCenter + (INT)(cos(M_PI+m_FreeSpacePerc/100.0f*M_PI*2.0f)*cx/2);
225 INT yRadial = yCenter - (INT)(sin(M_PI+m_FreeSpacePerc/100.0f*M_PI*2.0f)*cy/2);
226 Pie(pDrawItem->hDC,
227 pDrawItem->rcItem.left, pDrawItem->rcItem.top,
228 pDrawItem->rcItem.right, pDrawItem->rcItem.bottom - 10,
229 pDrawItem->rcItem.left, yCenter,
230 xRadial, yRadial);
231
232 SelectObject(pDrawItem->hDC, hBlueBrush);
233 Pie(pDrawItem->hDC,
234 pDrawItem->rcItem.left, pDrawItem->rcItem.top,
235 pDrawItem->rcItem.right, pDrawItem->rcItem.bottom - 10,
236 xRadial, yRadial,
237 pDrawItem->rcItem.left, yCenter);
238 SelectObject(pDrawItem->hDC, hbrOld);
239
240 HPEN hOldPen = (HPEN)SelectObject(pDrawItem->hDC, hDarkMagPen);
241 for (INT x = pDrawItem->rcItem.left; x < pDrawItem->rcItem.right; ++x)
242 {
243 if (m_FreeSpacePerc < 50 && x == xRadial)
244 SelectObject(pDrawItem->hDC, hDarkBluePen);
245
246 double cos_val = (x - xCenter)*2.0f/cx;
247 INT y = yCenter+(INT)(sin(acos(cos_val))*cy/2);
248 MoveToEx(pDrawItem->hDC, x, y, NULL);
249 LineTo(pDrawItem->hDC, x, y + 10);
250 }
251 SelectObject(pDrawItem->hDC, hOldPen);
252
253 DeleteObject(hBlueBrush);
254 DeleteObject(hMagBrush);
255 DeleteObject(hDarkBluePen);
256 DeleteObject(hDarkMagPen);
257 }
258 }
259
260 VOID
261 CDrvDefExt::InitGeneralPage(HWND hwndDlg)
262 {
263 WCHAR wszVolumeName[MAX_PATH+1] = {0};
264 WCHAR wszFileSystem[MAX_PATH+1] = {0};
265 WCHAR wszBuf[128];
266 BOOL bRet;
267
268 bRet = GetVolumeInformationW(m_wszDrive, wszVolumeName, _countof(wszVolumeName), NULL, NULL, NULL, wszFileSystem, _countof(wszFileSystem));
269 if (bRet)
270 {
271 /* Set volume label and filesystem */
272 SetDlgItemTextW(hwndDlg, 14000, wszVolumeName);
273 SetDlgItemTextW(hwndDlg, 14002, wszFileSystem);
274 }
275
276 /* Set drive type and icon */
277 UINT DriveType = GetDriveTypeW(m_wszDrive);
278 UINT IconId, TypeStrId = 0;
279 switch (DriveType)
280 {
281 case DRIVE_CDROM: IconId = IDI_SHELL_CDROM; TypeStrId = IDS_DRIVE_CDROM; break;
282 case DRIVE_REMOVABLE: IconId = IDI_SHELL_FLOPPY; break;
283 case DRIVE_RAMDISK: IconId = IDI_SHELL_RAMDISK; break;
284 default: IconId = IDI_SHELL_DRIVE; TypeStrId = IDS_DRIVE_FIXED;
285 }
286 HICON hIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IconId), IMAGE_ICON, 32, 32, LR_SHARED);
287 if (hIcon)
288 SendDlgItemMessageW(hwndDlg, 14016, STM_SETICON, (WPARAM)hIcon, 0);
289 if (TypeStrId && LoadStringW(shell32_hInstance, TypeStrId, wszBuf, _countof(wszBuf)))
290 SetDlgItemTextW(hwndDlg, 14001, wszBuf);
291
292 ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes;
293 if(GetDiskFreeSpaceExW(m_wszDrive, &FreeBytesAvailable, &TotalNumberOfBytes, NULL))
294 {
295 /* Init free space percentage used for drawing piechart */
296 m_FreeSpacePerc = (UINT)(FreeBytesAvailable.QuadPart * 100ull / TotalNumberOfBytes.QuadPart);
297
298 /* Used space */
299 if (SH_FormatByteSize(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf)))
300 SetDlgItemTextW(hwndDlg, 14003, wszBuf);
301
302 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf)))
303 SetDlgItemTextW(hwndDlg, 14004, wszBuf);
304
305 /* Free space */
306 if (SH_FormatByteSize(FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf)))
307 SetDlgItemTextW(hwndDlg, 14005, wszBuf);
308
309 if (StrFormatByteSizeW(FreeBytesAvailable.QuadPart, wszBuf, _countof(wszBuf)))
310 SetDlgItemTextW(hwndDlg, 14006, wszBuf);
311
312 /* Total space */
313 if (SH_FormatByteSize(TotalNumberOfBytes.QuadPart, wszBuf, _countof(wszBuf)))
314 SetDlgItemTextW(hwndDlg, 14007, wszBuf);
315
316 if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, wszBuf, _countof(wszBuf)))
317 SetDlgItemTextW(hwndDlg, 14008, wszBuf);
318 }
319
320 /* Set drive description */
321 WCHAR wszFormat[50];
322 GetDlgItemTextW(hwndDlg, 14009, wszFormat, _countof(wszFormat));
323 swprintf(wszBuf, wszFormat, m_wszDrive[0]);
324 SetDlgItemTextW(hwndDlg, 14009, wszBuf);
325 }
326
327 INT_PTR CALLBACK
328 CDrvDefExt::GeneralPageProc(
329 HWND hwndDlg,
330 UINT uMsg,
331 WPARAM wParam,
332 LPARAM lParam)
333 {
334 switch(uMsg)
335 {
336 case WM_INITDIALOG:
337 {
338 LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam;
339 if (ppsp == NULL)
340 break;
341
342 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(ppsp->lParam);
343 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pDrvDefExt);
344 pDrvDefExt->InitGeneralPage(hwndDlg);
345 return TRUE;
346 }
347 case WM_DRAWITEM:
348 {
349 LPDRAWITEMSTRUCT pDrawItem = (LPDRAWITEMSTRUCT)lParam;
350
351 if (pDrawItem->CtlID >= 14013 && pDrawItem->CtlID <= 14015)
352 {
353 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
354 pDrvDefExt->PaintStaticControls(hwndDlg, pDrawItem);
355 return TRUE;
356 }
357 break;
358 }
359 case WM_PAINT:
360 break;
361 case WM_COMMAND:
362 if (LOWORD(wParam) == 14010) /* Disk Cleanup */
363 {
364 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
365 WCHAR wszBuf[256];
366 DWORD cbBuf = sizeof(wszBuf);
367
368 if (RegGetValueW(HKEY_LOCAL_MACHINE,
369 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\CleanupPath",
370 NULL,
371 RRF_RT_REG_SZ,
372 NULL,
373 (PVOID)wszBuf,
374 &cbBuf) == ERROR_SUCCESS)
375 {
376 WCHAR wszCmd[MAX_PATH];
377
378 StringCbPrintfW(wszCmd, sizeof(wszCmd), wszBuf, pDrvDefExt->m_wszDrive[0]);
379
380 if (ShellExecuteW(hwndDlg, NULL, wszCmd, NULL, NULL, SW_SHOW) <= (HINSTANCE)32)
381 ERR("Failed to create cleanup process %ls\n", wszCmd);
382 }
383 }
384 else if (LOWORD(wParam) == 14000) /* Label */
385 {
386 if (HIWORD(wParam) == EN_CHANGE)
387 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
388 }
389 break;
390 case WM_NOTIFY:
391 if (((LPNMHDR)lParam)->hwndFrom == GetParent(hwndDlg))
392 {
393 /* Property Sheet */
394 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
395
396 if (lppsn->hdr.code == PSN_APPLY)
397 {
398 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
399 WCHAR wszBuf[256];
400
401 if (GetDlgItemTextW(hwndDlg, 14000, wszBuf, _countof(wszBuf)))
402 SetVolumeLabelW(pDrvDefExt->m_wszDrive, wszBuf);
403 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
404 return TRUE;
405 }
406 }
407 break;
408
409 default:
410 break;
411 }
412
413 return FALSE;
414 }
415
416 INT_PTR CALLBACK
417 CDrvDefExt::ExtraPageProc(
418 HWND hwndDlg,
419 UINT uMsg,
420 WPARAM wParam,
421 LPARAM lParam)
422 {
423 switch (uMsg)
424 {
425 case WM_INITDIALOG:
426 {
427 LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam;
428 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)ppsp->lParam);
429 return TRUE;
430 }
431 case WM_COMMAND:
432 {
433 WCHAR wszBuf[MAX_PATH];
434 DWORD cbBuf = sizeof(wszBuf);
435 CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
436
437 switch(LOWORD(wParam))
438 {
439 case 14000:
440 DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_CHECK_DISK), hwndDlg, ChkDskDlg, (LPARAM)pDrvDefExt->m_wszDrive);
441 break;
442 case 14001:
443 if (RegGetValueW(HKEY_LOCAL_MACHINE,
444 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",
445 NULL,
446 RRF_RT_REG_SZ,
447 NULL,
448 (PVOID)wszBuf,
449 &cbBuf) == ERROR_SUCCESS)
450 {
451 WCHAR wszCmd[MAX_PATH];
452
453 StringCbPrintfW(wszCmd, sizeof(wszCmd), wszBuf, pDrvDefExt->m_wszDrive[0]);
454
455 if (ShellExecuteW(hwndDlg, NULL, wszCmd, NULL, NULL, SW_SHOW) <= (HINSTANCE)32)
456 ERR("Failed to create defrag process %ls\n", wszCmd);
457 }
458 break;
459 case 14002:
460 if (RegGetValueW(HKEY_LOCAL_MACHINE,
461 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",
462 NULL,
463 RRF_RT_REG_EXPAND_SZ,
464 NULL,
465 (PVOID)wszBuf,
466 &cbBuf) == ERROR_SUCCESS)
467 {
468 if (ShellExecuteW(hwndDlg, NULL, wszBuf, NULL, NULL, SW_SHOW) <= (HINSTANCE)32)
469 ERR("Failed to create backup process %ls\n", wszBuf);
470 }
471 }
472 break;
473 }
474 }
475 return FALSE;
476 }
477
478 INT_PTR CALLBACK
479 CDrvDefExt::HardwarePageProc(
480 HWND hwndDlg,
481 UINT uMsg,
482 WPARAM wParam,
483 LPARAM lParam)
484 {
485 UNREFERENCED_PARAMETER(lParam);
486 UNREFERENCED_PARAMETER(wParam);
487
488 switch(uMsg)
489 {
490 case WM_INITDIALOG:
491 {
492 GUID Guid = GUID_DEVCLASS_DISKDRIVE;
493
494 /* create the hardware page */
495 DeviceCreateHardwarePageEx(hwndDlg, &Guid, 1, HWPD_STANDARDLIST);
496 break;
497 }
498 }
499
500 return FALSE;
501 }
502
503 CDrvDefExt::CDrvDefExt()
504 {
505 m_wszDrive[0] = L'\0';
506 }
507
508 CDrvDefExt::~CDrvDefExt()
509 {
510
511 }
512
513 HRESULT WINAPI
514 CDrvDefExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pDataObj, HKEY hkeyProgID)
515 {
516 FORMATETC format;
517 STGMEDIUM stgm;
518 HRESULT hr;
519
520 TRACE("%p %p %p %p\n", this, pidlFolder, pDataObj, hkeyProgID);
521
522 if (!pDataObj)
523 return E_FAIL;
524
525 format.cfFormat = CF_HDROP;
526 format.ptd = NULL;
527 format.dwAspect = DVASPECT_CONTENT;
528 format.lindex = -1;
529 format.tymed = TYMED_HGLOBAL;
530
531 hr = pDataObj->GetData(&format, &stgm);
532 if (FAILED(hr))
533 return hr;
534
535 if (!DragQueryFileW((HDROP)stgm.hGlobal, 0, m_wszDrive, _countof(m_wszDrive)))
536 {
537 ERR("DragQueryFileW failed\n");
538 ReleaseStgMedium(&stgm);
539 return E_FAIL;
540 }
541
542 ReleaseStgMedium(&stgm);
543 TRACE("Drive properties %ls\n", m_wszDrive);
544
545 return S_OK;
546 }
547
548 HRESULT WINAPI
549 CDrvDefExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
550 {
551 UNIMPLEMENTED;
552 return E_NOTIMPL;
553 }
554
555 HRESULT WINAPI
556 CDrvDefExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
557 {
558 UNIMPLEMENTED;
559 return E_NOTIMPL;
560 }
561
562 HRESULT WINAPI
563 CDrvDefExt::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax)
564 {
565 UNIMPLEMENTED;
566 return E_NOTIMPL;
567 }
568
569 HRESULT WINAPI
570 CDrvDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
571 {
572 HPROPSHEETPAGE hPage;
573
574 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_PROPERTIES,
575 GeneralPageProc,
576 (LPARAM)this,
577 NULL);
578 if (hPage)
579 pfnAddPage(hPage, lParam);
580
581 if (GetDriveTypeW(m_wszDrive) == DRIVE_FIXED)
582 {
583 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_TOOLS,
584 ExtraPageProc,
585 (LPARAM)this,
586 NULL);
587 if (hPage)
588 pfnAddPage(hPage, lParam);
589 }
590
591 hPage = SH_CreatePropertySheetPage(IDD_DRIVE_HARDWARE,
592 HardwarePageProc,
593 (LPARAM)this,
594 NULL);
595 if (hPage)
596 pfnAddPage(hPage, lParam);
597
598 return S_OK;
599 }
600
601 HRESULT WINAPI
602 CDrvDefExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam)
603 {
604 UNIMPLEMENTED;
605 return E_NOTIMPL;
606 }
607
608 HRESULT WINAPI
609 CDrvDefExt::SetSite(IUnknown *punk)
610 {
611 UNIMPLEMENTED;
612 return E_NOTIMPL;
613 }
614
615 HRESULT WINAPI
616 CDrvDefExt::GetSite(REFIID iid, void **ppvSite)
617 {
618 UNIMPLEMENTED;
619 return E_NOTIMPL;
620 }