[NTOS:KE/x64] Handle NMI vs swapgs race condition
[reactos.git] / dll / shellext / deskmon / deskmon.c
1 #include "precomp.h"
2
3 #include <tchar.h>
4 #include <winreg.h>
5 #include <cfgmgr32.h>
6
7 #define NDEBUG
8 #include <debug.h>
9
10 #include "resource.h"
11
12 static HINSTANCE hInstance;
13 static BOOL bFoundAdapter;
14 static DEVINST diAdapter;
15
16 #ifdef UNICODE
17 typedef INT_PTR (WINAPI *PDEVICEPROPERTIES)(HWND,LPCWSTR,LPCWSTR,BOOL);
18 #define FUNC_DEVICEPROPERTIES "DevicePropertiesW"
19 #else
20 typedef INT_PTR (WINAPI *PDEVICEPROPERTIES)(HWND,LPCSTR,LPCSTR,BOOL);
21 #define FUNC_DEVICEPROPERTIES "DevicePropertiesA"
22 #endif
23
24 /**
25 * @brief
26 * Converts a Hardware ID (DeviceID from EnumDisplayDevices)
27 * to an unique Device Instance ID.
28 *
29 * @param[in] lpDeviceID
30 * A pointer to a null-terminated string
31 * containing a Hardware ID concatenated with driver key.
32 * e.g. "Monitor\Default_Monitor\{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000"
33 *
34 * @return
35 * A pointer to a null-terminated string
36 * containing an unique Device Instance ID
37 * or NULL in case of error.
38 * e.g. "DISPLAY\DEFAULT_MONITOR\4&2ABFAA30&0&00000001&00&02"
39 *
40 * @remarks
41 * The caller must free the returned string with LocalFree.
42 */
43 static LPTSTR
44 GetMonitorDevInstID(LPCTSTR lpDeviceID)
45 {
46 CONFIGRET cr;
47 DEVINST diChild;
48 TCHAR szProperty[256];
49 DWORD dwSize;
50 LPTSTR lpDevInstId = NULL;
51
52 if (!bFoundAdapter)
53 return NULL;
54
55 /* Look for child monitor devices of selected video adapter */
56 cr = CM_Get_Child(&diChild, diAdapter, 0);
57 if (cr != CR_SUCCESS)
58 {
59 DPRINT1("CM_Get_Child failed: %d\n", cr);
60 return NULL;
61 }
62
63 do
64 {
65 /* Get Hardware ID for each of them */
66 dwSize = sizeof(szProperty) - sizeof(TCHAR);
67
68 cr = CM_Get_DevNode_Registry_Property(diChild,
69 CM_DRP_HARDWAREID,
70 NULL,
71 szProperty,
72 &dwSize,
73 0);
74 if (cr != CR_SUCCESS)
75 {
76 DPRINT1("CM_Get_DevNode_Registry_Property failed: %d\n", cr);
77 continue;
78 }
79
80 /* Concatenate with driver key */
81 _tcscat(szProperty, TEXT("\\"));
82 dwSize = sizeof(szProperty) - sizeof(TCHAR);
83 dwSize -= _tcslen(szProperty) * sizeof(TCHAR);
84
85 cr = CM_Get_DevNode_Registry_Property(diChild,
86 CM_DRP_DRIVER,
87 NULL,
88 szProperty + _tcslen(szProperty),
89 &dwSize,
90 0);
91 if (cr != CR_SUCCESS)
92 {
93 DPRINT1("CM_Get_DevNode_Registry_Property failed: %d\n", cr);
94 continue;
95 }
96
97 /* If the strings match, this is our monitor device node */
98 if (_tcscmp(szProperty, lpDeviceID) == 0)
99 {
100 cr = CM_Get_Device_ID_Size(&dwSize,
101 diChild,
102 0);
103 if (cr != CR_SUCCESS)
104 {
105 DPRINT1("CM_Get_Device_ID_Size failed: %d\n", cr);
106 break;
107 }
108
109 lpDevInstId = LocalAlloc(LMEM_FIXED,
110 (dwSize + 1) * sizeof(TCHAR));
111 if (lpDevInstId == NULL)
112 {
113 DPRINT1("LocalAlloc failed\n");
114 break;
115 }
116
117 cr = CM_Get_Device_ID(diChild,
118 lpDevInstId,
119 dwSize + 1,
120 0);
121 if (cr != CR_SUCCESS)
122 {
123 DPRINT1("CM_Get_Device_ID failed: %d\n", cr);
124 LocalFree((HLOCAL)lpDevInstId);
125 lpDevInstId = NULL;
126 }
127
128 break;
129 }
130 } while (CM_Get_Sibling(&diChild, diChild, 0) == CR_SUCCESS);
131
132 return lpDevInstId;
133 }
134
135 static VOID
136 ShowMonitorProperties(PDESKMONITOR This)
137 {
138 HMODULE hDevMgr;
139 PDEVICEPROPERTIES pDeviceProperties;
140 LPTSTR lpDevInstID;
141
142 if (This->SelMonitor != NULL)
143 {
144 lpDevInstID = GetMonitorDevInstID(This->SelMonitor->dd.DeviceID);
145 if (lpDevInstID != NULL)
146 {
147 hDevMgr = LoadLibrary(TEXT("devmgr.dll"));
148 if (hDevMgr != NULL)
149 {
150 pDeviceProperties = (PDEVICEPROPERTIES)GetProcAddress(hDevMgr,
151 FUNC_DEVICEPROPERTIES);
152 if (pDeviceProperties != NULL)
153 {
154 pDeviceProperties(This->hwndDlg,
155 NULL,
156 lpDevInstID,
157 FALSE);
158 }
159
160 FreeLibrary(hDevMgr);
161 }
162
163 LocalFree((HLOCAL)lpDevInstID);
164 }
165 }
166 }
167
168 static VOID
169 UpdateMonitorSelection(PDESKMONITOR This)
170 {
171 INT i;
172 LPTSTR lpDevInstID = NULL;
173
174 if (This->dwMonitorCount > 1)
175 {
176 This->SelMonitor = NULL;
177
178 i = (INT)SendDlgItemMessage(This->hwndDlg,
179 IDC_MONITORLIST,
180 LB_GETCURSEL,
181 0,
182 0);
183 if (i >= 0)
184 {
185 This->SelMonitor = (PDESKMONINFO)SendDlgItemMessage(This->hwndDlg,
186 IDC_MONITORLIST,
187 LB_GETITEMDATA,
188 (WPARAM)i,
189 0);
190 }
191 }
192 else
193 This->SelMonitor = This->Monitors;
194
195 if (This->SelMonitor != NULL)
196 lpDevInstID = GetMonitorDevInstID(This->SelMonitor->dd.DeviceID);
197
198 EnableWindow(GetDlgItem(This->hwndDlg,
199 IDC_MONITORPROPERTIES),
200 lpDevInstID != NULL && lpDevInstID[0] != TEXT('\0'));
201
202 if (lpDevInstID != NULL)
203 LocalFree((HLOCAL)lpDevInstID);
204 }
205
206 static VOID
207 UpdatePruningControls(PDESKMONITOR This)
208 {
209 EnableWindow(GetDlgItem(This->hwndDlg,
210 IDC_PRUNINGCHECK),
211 This->bModesPruned && !This->bKeyIsReadOnly);
212 CheckDlgButton(This->hwndDlg,
213 IDC_PRUNINGCHECK,
214 (This->bModesPruned && This->bPruningOn) ? BST_CHECKED : BST_UNCHECKED);
215 }
216
217 static VOID
218 GetPruningSettings(PDESKMONITOR This)
219 {
220 BOOL bModesPruned = FALSE, bKeyIsReadOnly = FALSE, bPruningOn = FALSE;
221
222 if (This->DeskExtInterface != NULL)
223 {
224 This->DeskExtInterface->GetPruningMode(This->DeskExtInterface->Context,
225 &bModesPruned,
226 &bKeyIsReadOnly,
227 &bPruningOn);
228 }
229
230 /* Check the boolean values against zero before assigning it to the bitfields! */
231 This->bModesPruned = (bModesPruned != FALSE);
232 This->bKeyIsReadOnly = (bKeyIsReadOnly != FALSE);
233 This->bPruningOn = (bPruningOn != FALSE);
234
235 UpdatePruningControls(This);
236 }
237
238 static VOID
239 UpdateRefreshFrequencyList(PDESKMONITOR This)
240 {
241 PDEVMODEW lpCurrentMode, lpMode;
242 TCHAR szBuffer[64];
243 DWORD dwIndex;
244 INT i;
245 BOOL bHasDef = FALSE;
246 BOOL bAdded = FALSE;
247
248 /* Fill the refresh rate combo box */
249 SendDlgItemMessage(This->hwndDlg,
250 IDC_REFRESHRATE,
251 CB_RESETCONTENT,
252 0,
253 0);
254
255 lpCurrentMode = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
256 dwIndex = 0;
257
258 do
259 {
260 lpMode = This->DeskExtInterface->EnumAllModes(This->DeskExtInterface->Context,
261 dwIndex++);
262 if (lpMode != NULL &&
263 lpMode->dmBitsPerPel == lpCurrentMode->dmBitsPerPel &&
264 lpMode->dmPelsWidth == lpCurrentMode->dmPelsWidth &&
265 lpMode->dmPelsHeight == lpCurrentMode->dmPelsHeight)
266 {
267 /* We're only interested in refresh rates for the current resolution and color depth */
268
269 if (lpMode->dmDisplayFrequency <= 1)
270 {
271 /* Default hardware frequency */
272 if (bHasDef)
273 continue;
274
275 bHasDef = TRUE;
276
277 if (!LoadString(hInstance,
278 IDS_USEDEFFRQUENCY,
279 szBuffer,
280 sizeof(szBuffer) / sizeof(szBuffer[0])))
281 {
282 szBuffer[0] = TEXT('\0');
283 }
284 }
285 else
286 {
287 TCHAR szFmt[64];
288
289 if (!LoadString(hInstance,
290 IDS_FREQFMT,
291 szFmt,
292 sizeof(szFmt) / sizeof(szFmt[0])))
293 {
294 szFmt[0] = TEXT('\0');
295 }
296
297 _sntprintf(szBuffer,
298 sizeof(szBuffer) / sizeof(szBuffer[0]),
299 szFmt,
300 lpMode->dmDisplayFrequency);
301 }
302
303 i = (INT)SendDlgItemMessage(This->hwndDlg,
304 IDC_REFRESHRATE,
305 CB_ADDSTRING,
306 0,
307 (LPARAM)szBuffer);
308 if (i >= 0)
309 {
310 bAdded = TRUE;
311
312 SendDlgItemMessage(This->hwndDlg,
313 IDC_REFRESHRATE,
314 CB_SETITEMDATA,
315 (WPARAM)i,
316 (LPARAM)lpMode);
317
318 if (lpMode->dmDisplayFrequency == lpCurrentMode->dmDisplayFrequency)
319 {
320 SendDlgItemMessage(This->hwndDlg,
321 IDC_REFRESHRATE,
322 CB_SETCURSEL,
323 (WPARAM)i,
324 0);
325 }
326 }
327 }
328
329 } while (lpMode != NULL);
330
331 EnableWindow(GetDlgItem(This->hwndDlg,
332 IDS_MONITORSETTINGSGROUP),
333 bAdded);
334 EnableWindow(GetDlgItem(This->hwndDlg,
335 IDS_REFRESHRATELABEL),
336 bAdded);
337 EnableWindow(GetDlgItem(This->hwndDlg,
338 IDC_REFRESHRATE),
339 bAdded);
340
341 GetPruningSettings(This);
342 }
343
344 static VOID
345 InitMonitorDialog(PDESKMONITOR This)
346 {
347 PDESKMONINFO pmi, pminext, *pmilink;
348 LPTSTR lpDeviceId;
349 CONFIGRET cr;
350 DISPLAY_DEVICE dd;
351 BOOL bRet;
352 INT i;
353 DWORD dwIndex;
354
355 /* Free all allocated monitors */
356 pmi = This->Monitors;
357 This->Monitors = NULL;
358 while (pmi != NULL)
359 {
360 pminext = pmi->Next;
361 LocalFree((HLOCAL)pmi);
362 pmi = pminext;
363 }
364
365 This->SelMonitor = NULL;
366 This->dwMonitorCount = 0;
367
368 bFoundAdapter = FALSE;
369 lpDeviceId = QueryDeskCplString(This->pdtobj,
370 RegisterClipboardFormat(DESK_EXT_DISPLAYID));
371
372 if (lpDeviceId != NULL && lpDeviceId[0] != TEXT('\0'))
373 {
374 cr = CM_Locate_DevNode(&diAdapter,
375 lpDeviceId,
376 CM_LOCATE_DEVNODE_NORMAL);
377 bFoundAdapter = (cr == CR_SUCCESS);
378
379 if (!bFoundAdapter)
380 DPRINT1("CM_Locate_DevNode failed: %d\n", cr);
381 }
382
383 if (This->lpDisplayDevice != NULL)
384 LocalFree((HLOCAL)This->lpDisplayDevice);
385
386 This->lpDisplayDevice = QueryDeskCplString(This->pdtobj,
387 RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE));
388
389 if (This->DeskExtInterface != NULL)
390 {
391 if (This->lpDisplayDevice != NULL)
392 {
393 /* Enumerate all monitors */
394 dwIndex = 0;
395 pmilink = &This->Monitors;
396
397 do
398 {
399 dd.cb = sizeof(dd);
400 bRet = EnumDisplayDevices(This->lpDisplayDevice,
401 dwIndex++,
402 &dd,
403 0);
404 if (bRet)
405 {
406 pmi = LocalAlloc(LMEM_FIXED,
407 sizeof(*pmi));
408 if (pmi != NULL)
409 {
410 CopyMemory(&pmi->dd,
411 &dd,
412 sizeof(dd));
413 pmi->Next = NULL;
414 *pmilink = pmi;
415 pmilink = &pmi->Next;
416
417 This->dwMonitorCount++;
418 }
419 }
420 } while (bRet);
421 }
422
423 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
424 }
425 else
426 This->lpDevModeOnInit = NULL;
427
428 This->lpSelDevMode = This->lpDevModeOnInit;
429
430 /* Setup the UI depending on how many monitors are attached */
431 if (This->dwMonitorCount == 0)
432 {
433 LPTSTR lpMonitorName;
434
435 /* This is a fallback, let's hope that desk.cpl can provide us with a monitor name */
436 lpMonitorName = QueryDeskCplString(This->pdtobj,
437 RegisterClipboardFormat(DESK_EXT_MONITORNAME));
438
439 SetDlgItemText(This->hwndDlg,
440 IDC_MONITORNAME,
441 lpMonitorName);
442
443 if (lpMonitorName != NULL)
444 LocalFree((HLOCAL)lpMonitorName);
445 }
446 else if (This->dwMonitorCount == 1)
447 {
448 This->SelMonitor = This->Monitors;
449 SetDlgItemText(This->hwndDlg,
450 IDC_MONITORNAME,
451 This->Monitors->dd.DeviceString);
452 }
453 else
454 {
455 SendDlgItemMessage(This->hwndDlg,
456 IDC_MONITORLIST,
457 LB_RESETCONTENT,
458 0,
459 0);
460
461 pmi = This->Monitors;
462 while (pmi != NULL)
463 {
464 i = (INT)SendDlgItemMessage(This->hwndDlg,
465 IDC_MONITORLIST,
466 LB_ADDSTRING,
467 0,
468 (LPARAM)pmi->dd.DeviceString);
469 if (i >= 0)
470 {
471 SendDlgItemMessage(This->hwndDlg,
472 IDC_MONITORLIST,
473 LB_SETITEMDATA,
474 (WPARAM)i,
475 (LPARAM)pmi);
476
477 if (This->SelMonitor == NULL)
478 {
479 SendDlgItemMessage(This->hwndDlg,
480 IDC_MONITORLIST,
481 LB_SETCURSEL,
482 (WPARAM)i,
483 0);
484
485 This->SelMonitor = pmi;
486 }
487 }
488
489 pmi = pmi->Next;
490 }
491 }
492
493 /* Show/Hide controls */
494 ShowWindow(GetDlgItem(This->hwndDlg,
495 IDC_MONITORNAME),
496 (This->dwMonitorCount <= 1 ? SW_SHOW : SW_HIDE));
497 ShowWindow(GetDlgItem(This->hwndDlg,
498 IDC_MONITORLIST),
499 (This->dwMonitorCount > 1 ? SW_SHOW : SW_HIDE));
500
501 UpdateRefreshFrequencyList(This);
502 UpdateMonitorSelection(This);
503 }
504
505 static VOID
506 UpdatePruningSelection(PDESKMONITOR This)
507 {
508 BOOL bPruningOn;
509
510 if (This->DeskExtInterface != NULL && This->bModesPruned && !This->bKeyIsReadOnly)
511 {
512 bPruningOn = IsDlgButtonChecked(This->hwndDlg,
513 IDC_PRUNINGCHECK) != BST_UNCHECKED;
514
515 if (bPruningOn != This->bPruningOn)
516 {
517 /* Tell desk.cpl to turn on/off pruning mode */
518 This->bPruningOn = bPruningOn;
519 This->DeskExtInterface->SetPruningMode(This->DeskExtInterface->Context,
520 bPruningOn);
521
522 /* Fill the refresh rate combobox again, we now receive a filtered
523 or unfiltered device mode list from desk.cpl (depending on whether
524 pruning is active or not) */
525 UpdateRefreshFrequencyList(This);
526
527 (void)PropSheet_Changed(GetParent(This->hwndDlg),
528 This->hwndDlg);
529 }
530 }
531 }
532
533 static VOID
534 UpdateRefreshRateSelection(PDESKMONITOR This)
535 {
536 PDEVMODEW lpCurrentDevMode;
537 INT i;
538
539 if (This->DeskExtInterface != NULL)
540 {
541 i = (INT)SendDlgItemMessage(This->hwndDlg,
542 IDC_REFRESHRATE,
543 CB_GETCURSEL,
544 0,
545 0);
546 if (i >= 0)
547 {
548 lpCurrentDevMode = This->lpSelDevMode;
549 This->lpSelDevMode = (PDEVMODEW)SendDlgItemMessage(This->hwndDlg,
550 IDC_REFRESHRATE,
551 CB_GETITEMDATA,
552 (WPARAM)i,
553 0);
554
555 if (This->lpSelDevMode != NULL && This->lpSelDevMode != lpCurrentDevMode)
556 {
557 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context,
558 This->lpSelDevMode);
559
560 UpdateRefreshFrequencyList(This);
561
562 (void)PropSheet_Changed(GetParent(This->hwndDlg),
563 This->hwndDlg);
564 }
565 }
566 }
567 }
568
569 static LONG
570 ApplyMonitorChanges(PDESKMONITOR This)
571 {
572 LONG lChangeRet;
573
574 if (This->DeskExtInterface != NULL)
575 {
576 /* Change the display settings through desk.cpl */
577 lChangeRet = DeskCplExtDisplaySaveSettings(This->DeskExtInterface,
578 This->hwndDlg);
579 if (lChangeRet == DISP_CHANGE_SUCCESSFUL)
580 {
581 /* Save the new mode */
582 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
583 This->lpSelDevMode = This->lpDevModeOnInit;
584 return PSNRET_NOERROR;
585 }
586 else if (lChangeRet == DISP_CHANGE_RESTART)
587 {
588 /* Notify desk.cpl that the user needs to reboot */
589 PropSheet_RestartWindows(GetParent(This->hwndDlg));
590 return PSNRET_NOERROR;
591 }
592 }
593
594 InitMonitorDialog(This);
595
596 return PSNRET_INVALID_NOCHANGEPAGE;
597 }
598
599 static VOID
600 ResetMonitorChanges(PDESKMONITOR This)
601 {
602 if (This->DeskExtInterface != NULL && This->lpDevModeOnInit != NULL)
603 {
604 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context,
605 This->lpDevModeOnInit);
606 }
607 }
608
609 static INT_PTR CALLBACK
610 MonitorDlgProc(HWND hwndDlg,
611 UINT uMsg,
612 WPARAM wParam,
613 LPARAM lParam)
614 {
615 PDESKMONITOR This;
616 INT_PTR Ret = 0;
617
618 if (uMsg != WM_INITDIALOG)
619 {
620 This = (PDESKMONITOR)GetWindowLongPtr(hwndDlg, DWLP_USER);
621 }
622
623 switch (uMsg)
624 {
625 case WM_INITDIALOG:
626 This = (PDESKMONITOR)((LPCPROPSHEETPAGE)lParam)->lParam;
627 This->hwndDlg = hwndDlg;
628 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This);
629
630 InitMonitorDialog(This);
631 Ret = TRUE;
632 break;
633
634 case WM_COMMAND:
635 switch (LOWORD(wParam))
636 {
637 case IDC_MONITORPROPERTIES:
638 ShowMonitorProperties(This);
639 break;
640
641 case IDC_MONITORLIST:
642 if (HIWORD(wParam) == LBN_SELCHANGE)
643 UpdateMonitorSelection(This);
644 break;
645
646 case IDC_PRUNINGCHECK:
647 if (HIWORD(wParam) == BN_CLICKED)
648 UpdatePruningSelection(This);
649 break;
650
651 case IDC_REFRESHRATE:
652 if (HIWORD(wParam) == CBN_SELCHANGE)
653 UpdateRefreshRateSelection(This);
654 break;
655 }
656 break;
657
658 case WM_NOTIFY:
659 {
660 NMHDR *nmh = (NMHDR *)lParam;
661
662 switch (nmh->code)
663 {
664 case PSN_APPLY:
665 {
666 SetWindowLongPtr(hwndDlg,
667 DWLP_MSGRESULT,
668 ApplyMonitorChanges(This));
669 Ret = TRUE;
670 break;
671 }
672
673 case PSN_RESET:
674 ResetMonitorChanges(This);
675 break;
676
677 case PSN_SETACTIVE:
678 UpdateRefreshFrequencyList(This);
679 break;
680 }
681 break;
682 }
683 }
684
685 return Ret;
686 }
687
688 static VOID
689 IDeskMonitor_Destroy(PDESKMONITOR This)
690 {
691 PDESKMONINFO pmi, pminext;
692
693 if (This->pdtobj != NULL)
694 {
695 IDataObject_Release(This->pdtobj);
696 This->pdtobj = NULL;
697 }
698
699 if (This->DeskExtInterface != NULL)
700 {
701 LocalFree((HLOCAL)This->DeskExtInterface);
702 This->DeskExtInterface = NULL;
703 }
704
705 if (This->lpDisplayDevice != NULL)
706 {
707 LocalFree((HLOCAL)This->lpDisplayDevice);
708 This->lpDisplayDevice = NULL;
709 }
710
711 /* Free all monitors */
712 pmi = This->Monitors;
713 This->Monitors = NULL;
714 while (pmi != NULL)
715 {
716 pminext = pmi->Next;
717 LocalFree((HLOCAL)pmi);
718 pmi = pminext;
719 }
720 }
721
722 ULONG
723 IDeskMonitor_AddRef(PDESKMONITOR This)
724 {
725 ULONG ret;
726
727 ret = InterlockedIncrement((PLONG)&This->ref);
728 if (ret == 1)
729 InterlockedIncrement(&dll_refs);
730
731 return ret;
732 }
733
734 ULONG
735 IDeskMonitor_Release(PDESKMONITOR This)
736 {
737 ULONG ret;
738
739 ret = InterlockedDecrement((PLONG)&This->ref);
740 if (ret == 0)
741 {
742 IDeskMonitor_Destroy(This);
743 InterlockedDecrement(&dll_refs);
744
745 HeapFree(GetProcessHeap(),
746 0,
747 This);
748 }
749
750 return ret;
751 }
752
753 HRESULT STDMETHODCALLTYPE
754 IDeskMonitor_QueryInterface(PDESKMONITOR This,
755 REFIID iid,
756 PVOID *pvObject)
757 {
758 *pvObject = NULL;
759
760 if (IsEqualIID(iid,
761 &IID_IShellPropSheetExt) ||
762 IsEqualIID(iid,
763 &IID_IUnknown))
764 {
765 *pvObject = impl_to_interface(This, IShellPropSheetExt);
766 }
767 else if (IsEqualIID(iid,
768 &IID_IShellExtInit))
769 {
770 *pvObject = impl_to_interface(This, IShellExtInit);
771 }
772 else if (IsEqualIID(iid,
773 &IID_IClassFactory))
774 {
775 *pvObject = impl_to_interface(This, IClassFactory);
776 }
777 else
778 {
779 DPRINT1("IDeskMonitor::QueryInterface(%p,%p): E_NOINTERFACE\n", iid, pvObject);
780 return E_NOINTERFACE;
781 }
782
783 IDeskMonitor_AddRef(This);
784 return S_OK;
785 }
786
787 HRESULT
788 IDeskMonitor_Initialize(PDESKMONITOR This,
789 LPCITEMIDLIST pidlFolder,
790 IDataObject *pdtobj,
791 HKEY hkeyProgID)
792 {
793 DPRINT1("IDeskMonitor::Initialize(%p,%p,%p)\n", pidlFolder, pdtobj, hkeyProgID);
794
795 if (pdtobj != NULL)
796 {
797 IDataObject_AddRef(pdtobj);
798 This->pdtobj = pdtobj;
799
800 /* Get a copy of the desk.cpl extension interface */
801 This->DeskExtInterface = QueryDeskCplExtInterface(This->pdtobj);
802 if (This->DeskExtInterface != NULL)
803 return S_OK;
804 }
805
806 return S_FALSE;
807 }
808
809 HRESULT
810 IDeskMonitor_AddPages(PDESKMONITOR This,
811 LPFNADDPROPSHEETPAGE pfnAddPage,
812 LPARAM lParam)
813 {
814 HPROPSHEETPAGE hpsp;
815 PROPSHEETPAGE psp;
816
817 DPRINT1("IDeskMonitor::AddPages(%p,%p)\n", pfnAddPage, lParam);
818
819 psp.dwSize = sizeof(psp);
820 psp.dwFlags = PSP_DEFAULT;
821 psp.hInstance = hInstance;
822 psp.pszTemplate = MAKEINTRESOURCE(IDD_MONITOR);
823 psp.pfnDlgProc = MonitorDlgProc;
824 psp.lParam = (LPARAM)This;
825
826 hpsp = CreatePropertySheetPage(&psp);
827 if (hpsp != NULL && pfnAddPage(hpsp, lParam))
828 return S_OK;
829
830 return S_FALSE;
831 }
832
833 HRESULT
834 IDeskMonitor_ReplacePage(PDESKMONITOR This,
835 EXPPS uPageID,
836 LPFNADDPROPSHEETPAGE pfnReplacePage,
837 LPARAM lParam)
838 {
839 DPRINT1("IDeskMonitor::ReplacePage(%u,%p,%p)\n", uPageID, pfnReplacePage, lParam);
840 return E_NOTIMPL;
841 }
842
843 HRESULT
844 IDeskMonitor_Constructor(REFIID riid,
845 LPVOID *ppv)
846 {
847 PDESKMONITOR This;
848 HRESULT hRet = E_OUTOFMEMORY;
849
850 DPRINT1("IDeskMonitor::Constructor(%p,%p)\n", riid, ppv);
851
852 This = HeapAlloc(GetProcessHeap(),
853 0,
854 sizeof(*This));
855 if (This != NULL)
856 {
857 ZeroMemory(This,
858 sizeof(*This));
859
860 IDeskMonitor_InitIface(This);
861
862 hRet = IDeskMonitor_QueryInterface(This,
863 riid,
864 ppv);
865 if (!SUCCEEDED(hRet))
866 IDeskMonitor_Release(This);
867 }
868
869 return hRet;
870 }
871
872 BOOL WINAPI
873 DllMain(HINSTANCE hinstDLL,
874 DWORD dwReason,
875 LPVOID lpvReserved)
876 {
877 switch (dwReason)
878 {
879 case DLL_PROCESS_ATTACH:
880 hInstance = hinstDLL;
881 DisableThreadLibraryCalls(hInstance);
882 break;
883 }
884
885 return TRUE;
886 }