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 295 This->lpDeviceId = QueryDeskCplString(This->pdtobj, 296 RegisterClipboardFormat(DESK_EXT_DISPLAYID)); 297 EnableWindow(GetDlgItem(This->hwndDlg, 298 IDC_ADAPTERPROPERTIES), 299 This->lpDeviceId != NULL && This->lpDeviceId[0] != TEXT('\0')); 300 lpAdapterName = QueryDeskCplString(This->pdtobj, 301 RegisterClipboardFormat(DESK_EXT_DISPLAYNAME)); 302 if (lpAdapterName != NULL) 303 { 304 SetDlgItemText(This->hwndDlg, 305 IDC_ADAPTERNAME, 306 lpAdapterName); 307 308 LocalFree((HLOCAL)lpAdapterName); 309 } 310 311 if (This->DeskExtInterface != NULL) 312 { 313 SetDlgItemTextW(This->hwndDlg, 314 IDC_CHIPTYPE, 315 This->DeskExtInterface->ChipType); 316 SetDlgItemTextW(This->hwndDlg, 317 IDC_DACTYPE, 318 This->DeskExtInterface->DacType); 319 SetDlgItemTextW(This->hwndDlg, 320 IDC_MEMORYSIZE, 321 This->DeskExtInterface->MemorySize); 322 SetDlgItemTextW(This->hwndDlg, 323 IDC_ADAPTERSTRING, 324 This->DeskExtInterface->AdapterString); 325 SetDlgItemTextW(This->hwndDlg, 326 IDC_BIOSINFORMATION, 327 This->DeskExtInterface->BiosString); 328 329 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context); 330 } 331 else 332 This->lpDevModeOnInit = NULL; 333 334 This->lpSelDevMode = This->lpDevModeOnInit; 335 } 336 337 static LONG 338 ApplyDisplayAdapterChanges(PDESKDISPLAYADAPTER This) 339 { 340 LONG lChangeRet; 341 342 if (This->DeskExtInterface != NULL) 343 { 344 /* Change the display settings through desk.cpl */ 345 lChangeRet = DeskCplExtDisplaySaveSettings(This->DeskExtInterface, 346 This->hwndDlg); 347 if (lChangeRet == DISP_CHANGE_SUCCESSFUL) 348 { 349 /* Save the new mode */ 350 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context); 351 This->lpSelDevMode = This->lpDevModeOnInit; 352 return PSNRET_NOERROR; 353 } 354 else if (lChangeRet == DISP_CHANGE_RESTART) 355 { 356 /* Notify desk.cpl that the user needs to reboot */ 357 PropSheet_RestartWindows(GetParent(This->hwndDlg)); 358 return PSNRET_NOERROR; 359 } 360 } 361 362 return PSNRET_INVALID_NOCHANGEPAGE; 363 } 364 365 static VOID 366 ResetDisplayAdapterChanges(PDESKDISPLAYADAPTER This) 367 { 368 if (This->DeskExtInterface != NULL && This->lpDevModeOnInit != NULL) 369 { 370 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context, 371 This->lpDevModeOnInit); 372 } 373 } 374 375 static INT_PTR CALLBACK 376 DisplayAdapterDlgProc(HWND hwndDlg, 377 UINT uMsg, 378 WPARAM wParam, 379 LPARAM lParam) 380 { 381 PDESKDISPLAYADAPTER This; 382 INT_PTR Ret = 0; 383 384 if (uMsg != WM_INITDIALOG) 385 { 386 This = (PDESKDISPLAYADAPTER)GetWindowLongPtr(hwndDlg, DWLP_USER); 387 } 388 389 switch (uMsg) 390 { 391 case WM_INITDIALOG: 392 This = (PDESKDISPLAYADAPTER)((LPCPROPSHEETPAGE)lParam)->lParam; 393 This->hwndDlg = hwndDlg; 394 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This); 395 396 InitDisplayAdapterDialog(This); 397 Ret = TRUE; 398 break; 399 400 case WM_COMMAND: 401 switch (LOWORD(wParam)) 402 { 403 case IDC_ADAPTERPROPERTIES: 404 ShowAdapterProperties(This); 405 break; 406 407 case IDC_LISTALLMODES: 408 ShowListAllModes(This); 409 break; 410 } 411 412 break; 413 414 case WM_NOTIFY: 415 { 416 NMHDR *nmh = (NMHDR *)lParam; 417 418 switch (nmh->code) 419 { 420 case PSN_APPLY: 421 { 422 SetWindowLongPtr(hwndDlg, 423 DWLP_MSGRESULT, 424 ApplyDisplayAdapterChanges(This)); 425 break; 426 } 427 428 case PSN_RESET: 429 ResetDisplayAdapterChanges(This); 430 break; 431 } 432 break; 433 } 434 } 435 436 return Ret; 437 } 438 439 static VOID 440 IDeskDisplayAdapter_Destroy(PDESKDISPLAYADAPTER This) 441 { 442 if (This->pdtobj != NULL) 443 { 444 IDataObject_Release(This->pdtobj); 445 This->pdtobj = NULL; 446 } 447 448 if (This->DeskExtInterface != NULL) 449 { 450 LocalFree((HLOCAL)This->DeskExtInterface); 451 This->DeskExtInterface = NULL; 452 } 453 454 if (This->lpDeviceId != NULL) 455 { 456 LocalFree((HLOCAL)This->lpDeviceId); 457 This->lpDeviceId = NULL; 458 } 459 } 460 461 ULONG 462 IDeskDisplayAdapter_AddRef(PDESKDISPLAYADAPTER This) 463 { 464 ULONG ret; 465 466 ret = InterlockedIncrement((PLONG)&This->ref); 467 if (ret == 1) 468 InterlockedIncrement(&dll_refs); 469 470 return ret; 471 } 472 473 ULONG 474 IDeskDisplayAdapter_Release(PDESKDISPLAYADAPTER This) 475 { 476 ULONG ret; 477 478 ret = InterlockedDecrement((PLONG)&This->ref); 479 if (ret == 0) 480 { 481 IDeskDisplayAdapter_Destroy(This); 482 InterlockedDecrement(&dll_refs); 483 484 HeapFree(GetProcessHeap(), 485 0, 486 This); 487 } 488 489 return ret; 490 } 491 492 HRESULT STDMETHODCALLTYPE 493 IDeskDisplayAdapter_QueryInterface(PDESKDISPLAYADAPTER This, 494 REFIID iid, 495 PVOID *pvObject) 496 { 497 *pvObject = NULL; 498 499 if (IsEqualIID(iid, 500 &IID_IShellPropSheetExt) || 501 IsEqualIID(iid, 502 &IID_IUnknown)) 503 { 504 *pvObject = impl_to_interface(This, IShellPropSheetExt); 505 } 506 else if (IsEqualIID(iid, 507 &IID_IShellExtInit)) 508 { 509 *pvObject = impl_to_interface(This, IShellExtInit); 510 } 511 else if (IsEqualIID(iid, 512 &IID_IClassFactory)) 513 { 514 *pvObject = impl_to_interface(This, IClassFactory); 515 } 516 else 517 { 518 DPRINT1("IDeskDisplayAdapter::QueryInterface(%p,%p): E_NOINTERFACE\n", iid, pvObject); 519 return E_NOINTERFACE; 520 } 521 522 IDeskDisplayAdapter_AddRef(This); 523 return S_OK; 524 } 525 526 HRESULT 527 IDeskDisplayAdapter_Initialize(PDESKDISPLAYADAPTER This, 528 LPCITEMIDLIST pidlFolder, 529 IDataObject *pdtobj, 530 HKEY hkeyProgID) 531 { 532 DPRINT1("IDeskDisplayAdapter::Initialize(%p,%p,%p)\n", pidlFolder, pdtobj, hkeyProgID); 533 534 if (pdtobj != NULL) 535 { 536 IDataObject_AddRef(pdtobj); 537 This->pdtobj = pdtobj; 538 539 /* Get a copy of the desk.cpl extension interface */ 540 This->DeskExtInterface = QueryDeskCplExtInterface(This->pdtobj); 541 if (This->DeskExtInterface != NULL) 542 return S_OK; 543 } 544 545 return S_FALSE; 546 } 547 548 HRESULT 549 IDeskDisplayAdapter_AddPages(PDESKDISPLAYADAPTER This, 550 LPFNADDPROPSHEETPAGE pfnAddPage, 551 LPARAM lParam) 552 { 553 HPROPSHEETPAGE hpsp; 554 PROPSHEETPAGE psp; 555 556 DPRINT1("IDeskDisplayAdapter::AddPages(%p,%p)\n", pfnAddPage, lParam); 557 558 psp.dwSize = sizeof(psp); 559 psp.dwFlags = PSP_DEFAULT; 560 psp.hInstance = hInstance; 561 psp.pszTemplate = MAKEINTRESOURCE(IDD_DISPLAYADAPTER); 562 psp.pfnDlgProc = DisplayAdapterDlgProc; 563 psp.lParam = (LPARAM)This; 564 565 hpsp = CreatePropertySheetPage(&psp); 566 if (hpsp != NULL && pfnAddPage(hpsp, lParam)) 567 return S_OK; 568 569 return S_FALSE; 570 } 571 572 HRESULT 573 IDeskDisplayAdapter_ReplacePage(PDESKDISPLAYADAPTER This, 574 EXPPS uPageID, 575 LPFNADDPROPSHEETPAGE pfnReplacePage, 576 LPARAM lParam) 577 { 578 DPRINT1("IDeskDisplayAdapter::ReplacePage(%u,%p,%p)\n", uPageID, pfnReplacePage, lParam); 579 return E_NOTIMPL; 580 } 581 582 HRESULT 583 IDeskDisplayAdapter_Constructor(REFIID riid, 584 LPVOID *ppv) 585 { 586 PDESKDISPLAYADAPTER This; 587 HRESULT hRet = E_OUTOFMEMORY; 588 589 DPRINT1("IDeskDisplayAdapter::Constructor(%p,%p)\n", riid, ppv); 590 591 This = HeapAlloc(GetProcessHeap(), 592 0, 593 sizeof(*This)); 594 if (This != NULL) 595 { 596 ZeroMemory(This, 597 sizeof(*This)); 598 599 IDeskDisplayAdapter_InitIface(This); 600 601 hRet = IDeskDisplayAdapter_QueryInterface(This, 602 riid, 603 ppv); 604 if (!SUCCEEDED(hRet)) 605 IDeskDisplayAdapter_Release(This); 606 } 607 608 return hRet; 609 } 610 611 BOOL WINAPI 612 DllMain(HINSTANCE hinstDLL, 613 DWORD dwReason, 614 LPVOID lpvReserved) 615 { 616 switch (dwReason) 617 { 618 case DLL_PROCESS_ATTACH: 619 hInstance = hinstDLL; 620 DisableThreadLibraryCalls(hInstance); 621 break; 622 } 623 624 return TRUE; 625 } 626