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
GetColorDescription(PDEVMODEW lpDevMode,LPTSTR lpBuffer,DWORD dwBufferLen)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
GetRefreshRateDescription(PDEVMODEW lpDevMode,LPTSTR lpBuffer,DWORD dwBufferLen)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
InitListAllModesDialog(PDESKDISPLAYADAPTER This,HWND hwndListAllModesDlg)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
ChangeSelectedMode(PDESKDISPLAYADAPTER This,HWND hwndListAllModesDlg)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
ListAllModesDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
ShowListAllModes(PDESKDISPLAYADAPTER This)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
ShowAdapterProperties(PDESKDISPLAYADAPTER This)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
InitDisplayAdapterDialog(PDESKDISPLAYADAPTER This)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
ApplyDisplayAdapterChanges(PDESKDISPLAYADAPTER This)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
ResetDisplayAdapterChanges(PDESKDISPLAYADAPTER This)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
DisplayAdapterDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
IDeskDisplayAdapter_Destroy(PDESKDISPLAYADAPTER This)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
IDeskDisplayAdapter_AddRef(PDESKDISPLAYADAPTER This)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
IDeskDisplayAdapter_Release(PDESKDISPLAYADAPTER This)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
IDeskDisplayAdapter_QueryInterface(PDESKDISPLAYADAPTER This,REFIID iid,PVOID * pvObject)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
IDeskDisplayAdapter_Initialize(PDESKDISPLAYADAPTER This,LPCITEMIDLIST pidlFolder,IDataObject * pdtobj,HKEY hkeyProgID)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
IDeskDisplayAdapter_AddPages(PDESKDISPLAYADAPTER This,LPFNADDPROPSHEETPAGE pfnAddPage,LPARAM lParam)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
IDeskDisplayAdapter_ReplacePage(PDESKDISPLAYADAPTER This,EXPPS uPageID,LPFNADDPROPSHEETPAGE pfnReplacePage,LPARAM lParam)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
IDeskDisplayAdapter_Constructor(REFIID riid,LPVOID * ppv)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
DllMain(HINSTANCE hinstDLL,DWORD dwReason,LPVOID lpvReserved)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