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