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