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 } 887