xref: /reactos/dll/shellext/deskadp/deskadp.c (revision cb6b07ee)
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