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