1 #include "precomp.h" 2 3 #include <tchar.h> 4 5 #define NDEBUG 6 #include <debug.h> 7 8 #include "resource.h" 9 10 static HINSTANCE hInstance; 11 12 typedef INT_PTR (WINAPI *PDEVICEPROPERTIESW)(HWND,LPCWSTR,LPCWSTR,BOOL); 13 14 static VOID 15 GetColorDescription(PDEVMODEW lpDevMode, 16 LPTSTR lpBuffer, 17 DWORD dwBufferLen) 18 { 19 UINT uid = 0; 20 21 switch (lpDevMode->dmBitsPerPel) 22 { 23 case 4: 24 uid = IDS_4BPP; 25 break; 26 case 8: 27 uid = IDS_8BPP; 28 break; 29 case 15: 30 uid = IDS_15BPP; 31 break; 32 case 16: 33 uid = IDS_16BPP; 34 break; 35 case 24: 36 uid = IDS_24BPP; 37 break; 38 case 32: 39 uid = IDS_32BPP; 40 break; 41 } 42 43 if (uid == 0 || 44 !LoadString(hInstance, 45 uid, 46 lpBuffer, 47 dwBufferLen)) 48 { 49 lpBuffer[0] = TEXT('\0'); 50 } 51 } 52 53 static VOID 54 GetRefreshRateDescription(PDEVMODEW lpDevMode, 55 LPTSTR lpBuffer, 56 DWORD dwBufferLen) 57 { 58 TCHAR szFormat[64]; 59 60 if (lpDevMode->dmDisplayFrequency <= 1) 61 { 62 if (!LoadString(hInstance, 63 IDS_DEFREFRESHRATE, 64 lpBuffer, 65 dwBufferLen)) 66 { 67 lpBuffer[0] = TEXT('\0'); 68 } 69 } 70 else 71 { 72 if (!LoadString(hInstance, 73 IDES_REFRESHRATEFMT, 74 szFormat, 75 sizeof(szFormat) / sizeof(szFormat[0]))) 76 { 77 szFormat[0] = TEXT('\0'); 78 } 79 80 _sntprintf(lpBuffer, 81 dwBufferLen, 82 szFormat, 83 lpDevMode->dmDisplayFrequency); 84 } 85 } 86 87 static VOID 88 InitListAllModesDialog(PDESKDISPLAYADAPTER This, 89 HWND hwndListAllModesDlg) 90 { 91 TCHAR szFormat[64], szBuffer[64], szColors[64], szRefreshRate[64]; 92 PDEVMODEW lpDevMode, lpCurrentDevMode; 93 DWORD dwIndex = 0; 94 INT i; 95 96 if (This->DeskExtInterface != NULL) 97 { 98 if (!LoadString(hInstance, 99 IDS_MODEFMT, 100 szFormat, 101 sizeof(szFormat) / sizeof(szFormat[0]))) 102 { 103 szFormat[0] = TEXT('\0'); 104 } 105 106 lpCurrentDevMode = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context); 107 108 do 109 { 110 lpDevMode = This->DeskExtInterface->EnumAllModes(This->DeskExtInterface->Context, 111 dwIndex++); 112 if (lpDevMode != NULL) 113 { 114 GetColorDescription(lpDevMode, 115 szColors, 116 sizeof(szColors) / sizeof(szColors[0])); 117 118 GetRefreshRateDescription(lpDevMode, 119 szRefreshRate, 120 sizeof(szRefreshRate) / sizeof(szRefreshRate[0])); 121 122 _sntprintf(szBuffer, 123 sizeof(szBuffer) / sizeof(szBuffer[0]), 124 szFormat, 125 lpDevMode->dmPelsWidth, 126 lpDevMode->dmPelsHeight, 127 szColors, 128 szRefreshRate); 129 130 i = (INT)SendDlgItemMessage(hwndListAllModesDlg, 131 IDC_ALLVALIDMODES, 132 LB_ADDSTRING, 133 0, 134 (LPARAM)szBuffer); 135 if (i >= 0) 136 { 137 SendDlgItemMessage(hwndListAllModesDlg, 138 IDC_ALLVALIDMODES, 139 LB_SETITEMDATA, 140 (WPARAM)i, 141 (LPARAM)lpDevMode); 142 143 if (lpDevMode == lpCurrentDevMode) 144 { 145 SendDlgItemMessage(hwndListAllModesDlg, 146 IDC_ALLVALIDMODES, 147 LB_SETCURSEL, 148 (WPARAM)i, 149 0); 150 } 151 } 152 } 153 154 } while (lpDevMode != NULL); 155 } 156 } 157 158 static BOOL 159 ChangeSelectedMode(PDESKDISPLAYADAPTER This, 160 HWND hwndListAllModesDlg) 161 { 162 INT i; 163 PDEVMODEW lpSelDevMode = NULL; 164 BOOL bRet = FALSE; 165 166 i = (INT)SendDlgItemMessage(hwndListAllModesDlg, 167 IDC_ALLVALIDMODES, 168 LB_GETCURSEL, 169 0, 170 0); 171 172 if (i >= 0) 173 { 174 lpSelDevMode = (PDEVMODEW)SendDlgItemMessage(hwndListAllModesDlg, 175 IDC_ALLVALIDMODES, 176 LB_GETITEMDATA, 177 (WPARAM)i, 178 0); 179 } 180 181 if (lpSelDevMode != NULL) 182 { 183 This->lpSelDevMode = lpSelDevMode; 184 bRet = TRUE; 185 } 186 187 return bRet; 188 } 189 190 static INT_PTR CALLBACK 191 ListAllModesDlgProc(HWND hwndDlg, 192 UINT uMsg, 193 WPARAM wParam, 194 LPARAM lParam) 195 { 196 PDESKDISPLAYADAPTER This; 197 INT_PTR Ret = 0; 198 199 if (uMsg != WM_INITDIALOG) 200 { 201 This = (PDESKDISPLAYADAPTER)GetWindowLongPtr(hwndDlg, DWLP_USER); 202 } 203 204 switch (uMsg) 205 { 206 case WM_INITDIALOG: 207 This = (PDESKDISPLAYADAPTER)lParam; 208 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This); 209 210 InitListAllModesDialog(This, 211 hwndDlg); 212 Ret = TRUE; 213 break; 214 215 case WM_COMMAND: 216 switch (LOWORD(wParam)) 217 { 218 case IDOK: 219 if (ChangeSelectedMode(This, 220 hwndDlg)) 221 { 222 EndDialog(hwndDlg, 223 IDOK); 224 } 225 break; 226 227 case IDCANCEL: 228 EndDialog(hwndDlg, 229 IDCANCEL); 230 break; 231 } 232 break; 233 234 case WM_CLOSE: 235 EndDialog(hwndDlg, 236 IDCANCEL); 237 break; 238 } 239 240 return Ret; 241 } 242 243 static VOID 244 ShowListAllModes(PDESKDISPLAYADAPTER This) 245 { 246 PDEVMODEW lpPrevSel; 247 248 lpPrevSel = This->lpSelDevMode; 249 250 if (This->DeskExtInterface != NULL && 251 DialogBoxParam(hInstance, 252 MAKEINTRESOURCE(IDD_LISTALLMODES), 253 This->hwndDlg, 254 ListAllModesDlgProc, 255 (LPARAM)This) == IDOK) 256 { 257 if (lpPrevSel != This->lpSelDevMode) 258 { 259 (void)PropSheet_Changed(GetParent(This->hwndDlg), 260 This->hwndDlg); 261 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context, 262 This->lpSelDevMode); 263 } 264 } 265 } 266 267 static VOID 268 ShowAdapterProperties(PDESKDISPLAYADAPTER This) 269 { 270 HMODULE hDevMgr; 271 PDEVICEPROPERTIESW pDevicePropertiesW; 272 273 hDevMgr = LoadLibrary(TEXT("devmgr.dll")); 274 if (hDevMgr != NULL) 275 { 276 pDevicePropertiesW = (PDEVICEPROPERTIESW)GetProcAddress(hDevMgr, 277 "DevicePropertiesW"); 278 if (pDevicePropertiesW != NULL) 279 { 280 pDevicePropertiesW(This->hwndDlg, 281 NULL, 282 This->lpDeviceId, 283 FALSE); 284 } 285 286 FreeLibrary(hDevMgr); 287 } 288 } 289 290 static VOID 291 InitDisplayAdapterDialog(PDESKDISPLAYADAPTER This) 292 { 293 LPTSTR lpAdapterName; 294 TCHAR lpNA[64]; 295 296 This->lpDeviceId = QueryDeskCplString(This->pdtobj, 297 RegisterClipboardFormat(DESK_EXT_DISPLAYID)); 298 EnableWindow(GetDlgItem(This->hwndDlg, 299 IDC_ADAPTERPROPERTIES), 300 This->lpDeviceId != NULL && This->lpDeviceId[0] != TEXT('\0')); 301 lpAdapterName = QueryDeskCplString(This->pdtobj, 302 RegisterClipboardFormat(DESK_EXT_DISPLAYNAME)); 303 if (lpAdapterName != NULL) 304 { 305 SetDlgItemText(This->hwndDlg, 306 IDC_ADAPTERNAME, 307 lpAdapterName); 308 309 LocalFree((HLOCAL)lpAdapterName); 310 } 311 312 LoadString(hInstance, 313 IDS_NOTAVAIL, 314 lpNA, 315 _countof(lpNA)); 316 317 if (This->DeskExtInterface != NULL) 318 { 319 SetDlgItemTextW(This->hwndDlg, 320 IDC_CHIPTYPE, 321 *(This->DeskExtInterface->ChipType) ? This->DeskExtInterface->ChipType : lpNA); 322 SetDlgItemTextW(This->hwndDlg, 323 IDC_DACTYPE, 324 *(This->DeskExtInterface->DacType) ? This->DeskExtInterface->DacType : lpNA); 325 SetDlgItemTextW(This->hwndDlg, 326 IDC_MEMORYSIZE, 327 *(This->DeskExtInterface->MemorySize) ? This->DeskExtInterface->MemorySize : lpNA); 328 SetDlgItemTextW(This->hwndDlg, 329 IDC_ADAPTERSTRING, 330 *(This->DeskExtInterface->AdapterString) ? This->DeskExtInterface->AdapterString : lpNA); 331 SetDlgItemTextW(This->hwndDlg, 332 IDC_BIOSINFORMATION, 333 *(This->DeskExtInterface->BiosString) ? This->DeskExtInterface->BiosString : lpNA); 334 335 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context); 336 } 337 else 338 { 339 This->lpDevModeOnInit = NULL; 340 SetDlgItemTextW(This->hwndDlg, IDC_CHIPTYPE, lpNA); 341 SetDlgItemTextW(This->hwndDlg, IDC_DACTYPE, lpNA); 342 SetDlgItemTextW(This->hwndDlg, IDC_MEMORYSIZE, lpNA); 343 SetDlgItemTextW(This->hwndDlg, IDC_ADAPTERSTRING, lpNA); 344 SetDlgItemTextW(This->hwndDlg, IDC_BIOSINFORMATION, lpNA); 345 } 346 347 This->lpSelDevMode = This->lpDevModeOnInit; 348 } 349 350 static LONG 351 ApplyDisplayAdapterChanges(PDESKDISPLAYADAPTER This) 352 { 353 LONG lChangeRet; 354 355 if (This->DeskExtInterface != NULL) 356 { 357 /* Change the display settings through desk.cpl */ 358 lChangeRet = DeskCplExtDisplaySaveSettings(This->DeskExtInterface, 359 This->hwndDlg); 360 if (lChangeRet == DISP_CHANGE_SUCCESSFUL) 361 { 362 /* Save the new mode */ 363 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context); 364 This->lpSelDevMode = This->lpDevModeOnInit; 365 return PSNRET_NOERROR; 366 } 367 else if (lChangeRet == DISP_CHANGE_RESTART) 368 { 369 /* Notify desk.cpl that the user needs to reboot */ 370 PropSheet_RestartWindows(GetParent(This->hwndDlg)); 371 return PSNRET_NOERROR; 372 } 373 } 374 375 return PSNRET_INVALID_NOCHANGEPAGE; 376 } 377 378 static VOID 379 ResetDisplayAdapterChanges(PDESKDISPLAYADAPTER This) 380 { 381 if (This->DeskExtInterface != NULL && This->lpDevModeOnInit != NULL) 382 { 383 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context, 384 This->lpDevModeOnInit); 385 } 386 } 387 388 static INT_PTR CALLBACK 389 DisplayAdapterDlgProc(HWND hwndDlg, 390 UINT uMsg, 391 WPARAM wParam, 392 LPARAM lParam) 393 { 394 PDESKDISPLAYADAPTER This; 395 INT_PTR Ret = 0; 396 397 if (uMsg != WM_INITDIALOG) 398 { 399 This = (PDESKDISPLAYADAPTER)GetWindowLongPtr(hwndDlg, DWLP_USER); 400 } 401 402 switch (uMsg) 403 { 404 case WM_INITDIALOG: 405 This = (PDESKDISPLAYADAPTER)((LPCPROPSHEETPAGE)lParam)->lParam; 406 This->hwndDlg = hwndDlg; 407 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This); 408 409 InitDisplayAdapterDialog(This); 410 Ret = TRUE; 411 break; 412 413 case WM_COMMAND: 414 switch (LOWORD(wParam)) 415 { 416 case IDC_ADAPTERPROPERTIES: 417 ShowAdapterProperties(This); 418 break; 419 420 case IDC_LISTALLMODES: 421 ShowListAllModes(This); 422 break; 423 } 424 425 break; 426 427 case WM_NOTIFY: 428 { 429 NMHDR *nmh = (NMHDR *)lParam; 430 431 switch (nmh->code) 432 { 433 case PSN_APPLY: 434 { 435 SetWindowLongPtr(hwndDlg, 436 DWLP_MSGRESULT, 437 ApplyDisplayAdapterChanges(This)); 438 Ret = TRUE; 439 break; 440 } 441 442 case PSN_RESET: 443 ResetDisplayAdapterChanges(This); 444 break; 445 } 446 break; 447 } 448 } 449 450 return Ret; 451 } 452 453 static VOID 454 IDeskDisplayAdapter_Destroy(PDESKDISPLAYADAPTER This) 455 { 456 if (This->pdtobj != NULL) 457 { 458 IDataObject_Release(This->pdtobj); 459 This->pdtobj = NULL; 460 } 461 462 if (This->DeskExtInterface != NULL) 463 { 464 LocalFree((HLOCAL)This->DeskExtInterface); 465 This->DeskExtInterface = NULL; 466 } 467 468 if (This->lpDeviceId != NULL) 469 { 470 LocalFree((HLOCAL)This->lpDeviceId); 471 This->lpDeviceId = NULL; 472 } 473 } 474 475 ULONG 476 IDeskDisplayAdapter_AddRef(PDESKDISPLAYADAPTER This) 477 { 478 ULONG ret; 479 480 ret = InterlockedIncrement((PLONG)&This->ref); 481 if (ret == 1) 482 InterlockedIncrement(&dll_refs); 483 484 return ret; 485 } 486 487 ULONG 488 IDeskDisplayAdapter_Release(PDESKDISPLAYADAPTER This) 489 { 490 ULONG ret; 491 492 ret = InterlockedDecrement((PLONG)&This->ref); 493 if (ret == 0) 494 { 495 IDeskDisplayAdapter_Destroy(This); 496 InterlockedDecrement(&dll_refs); 497 498 HeapFree(GetProcessHeap(), 499 0, 500 This); 501 } 502 503 return ret; 504 } 505 506 HRESULT STDMETHODCALLTYPE 507 IDeskDisplayAdapter_QueryInterface(PDESKDISPLAYADAPTER This, 508 REFIID iid, 509 PVOID *pvObject) 510 { 511 *pvObject = NULL; 512 513 if (IsEqualIID(iid, 514 &IID_IShellPropSheetExt) || 515 IsEqualIID(iid, 516 &IID_IUnknown)) 517 { 518 *pvObject = impl_to_interface(This, IShellPropSheetExt); 519 } 520 else if (IsEqualIID(iid, 521 &IID_IShellExtInit)) 522 { 523 *pvObject = impl_to_interface(This, IShellExtInit); 524 } 525 else if (IsEqualIID(iid, 526 &IID_IClassFactory)) 527 { 528 *pvObject = impl_to_interface(This, IClassFactory); 529 } 530 else 531 { 532 DPRINT1("IDeskDisplayAdapter::QueryInterface(%p,%p): E_NOINTERFACE\n", iid, pvObject); 533 return E_NOINTERFACE; 534 } 535 536 IDeskDisplayAdapter_AddRef(This); 537 return S_OK; 538 } 539 540 HRESULT 541 IDeskDisplayAdapter_Initialize(PDESKDISPLAYADAPTER This, 542 LPCITEMIDLIST pidlFolder, 543 IDataObject *pdtobj, 544 HKEY hkeyProgID) 545 { 546 DPRINT1("IDeskDisplayAdapter::Initialize(%p,%p,%p)\n", pidlFolder, pdtobj, hkeyProgID); 547 548 if (pdtobj != NULL) 549 { 550 IDataObject_AddRef(pdtobj); 551 This->pdtobj = pdtobj; 552 553 /* Get a copy of the desk.cpl extension interface */ 554 This->DeskExtInterface = QueryDeskCplExtInterface(This->pdtobj); 555 if (This->DeskExtInterface != NULL) 556 return S_OK; 557 } 558 559 return S_FALSE; 560 } 561 562 HRESULT 563 IDeskDisplayAdapter_AddPages(PDESKDISPLAYADAPTER This, 564 LPFNADDPROPSHEETPAGE pfnAddPage, 565 LPARAM lParam) 566 { 567 HPROPSHEETPAGE hpsp; 568 PROPSHEETPAGE psp; 569 570 DPRINT1("IDeskDisplayAdapter::AddPages(%p,%p)\n", pfnAddPage, lParam); 571 572 psp.dwSize = sizeof(psp); 573 psp.dwFlags = PSP_DEFAULT; 574 psp.hInstance = hInstance; 575 psp.pszTemplate = MAKEINTRESOURCE(IDD_DISPLAYADAPTER); 576 psp.pfnDlgProc = DisplayAdapterDlgProc; 577 psp.lParam = (LPARAM)This; 578 579 hpsp = CreatePropertySheetPage(&psp); 580 if (hpsp != NULL && pfnAddPage(hpsp, lParam)) 581 return S_OK; 582 583 return S_FALSE; 584 } 585 586 HRESULT 587 IDeskDisplayAdapter_ReplacePage(PDESKDISPLAYADAPTER This, 588 EXPPS uPageID, 589 LPFNADDPROPSHEETPAGE pfnReplacePage, 590 LPARAM lParam) 591 { 592 DPRINT1("IDeskDisplayAdapter::ReplacePage(%u,%p,%p)\n", uPageID, pfnReplacePage, lParam); 593 return E_NOTIMPL; 594 } 595 596 HRESULT 597 IDeskDisplayAdapter_Constructor(REFIID riid, 598 LPVOID *ppv) 599 { 600 PDESKDISPLAYADAPTER This; 601 HRESULT hRet = E_OUTOFMEMORY; 602 603 DPRINT1("IDeskDisplayAdapter::Constructor(%p,%p)\n", riid, ppv); 604 605 This = HeapAlloc(GetProcessHeap(), 606 0, 607 sizeof(*This)); 608 if (This != NULL) 609 { 610 ZeroMemory(This, 611 sizeof(*This)); 612 613 IDeskDisplayAdapter_InitIface(This); 614 615 hRet = IDeskDisplayAdapter_QueryInterface(This, 616 riid, 617 ppv); 618 if (!SUCCEEDED(hRet)) 619 IDeskDisplayAdapter_Release(This); 620 } 621 622 return hRet; 623 } 624 625 BOOL WINAPI 626 DllMain(HINSTANCE hinstDLL, 627 DWORD dwReason, 628 LPVOID lpvReserved) 629 { 630 switch (dwReason) 631 { 632 case DLL_PROCESS_ATTACH: 633 hInstance = hinstDLL; 634 DisableThreadLibraryCalls(hInstance); 635 break; 636 } 637 638 return TRUE; 639 } 640