Sync with trunk r63647.
[reactos.git] / dll / shellext / deskadp / deskadp.c
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,
202 DWL_USER);
203 }
204
205 switch (uMsg)
206 {
207 case WM_INITDIALOG:
208 This = (PDESKDISPLAYADAPTER)lParam;
209 SetWindowLongPtr(hwndDlg,
210 DWL_USER,
211 (LONG_PTR)This);
212
213 InitListAllModesDialog(This,
214 hwndDlg);
215 Ret = TRUE;
216 break;
217
218 case WM_COMMAND:
219 switch (LOWORD(wParam))
220 {
221 case IDOK:
222 if (ChangeSelectedMode(This,
223 hwndDlg))
224 {
225 EndDialog(hwndDlg,
226 IDOK);
227 }
228 break;
229
230 case IDCANCEL:
231 EndDialog(hwndDlg,
232 IDCANCEL);
233 break;
234 }
235 break;
236
237 case WM_CLOSE:
238 EndDialog(hwndDlg,
239 IDCANCEL);
240 break;
241 }
242
243 return Ret;
244 }
245
246 static VOID
247 ShowListAllModes(PDESKDISPLAYADAPTER This)
248 {
249 PDEVMODEW lpPrevSel;
250
251 lpPrevSel = This->lpSelDevMode;
252
253 if (This->DeskExtInterface != NULL &&
254 DialogBoxParam(hInstance,
255 MAKEINTRESOURCE(IDD_LISTALLMODES),
256 This->hwndDlg,
257 ListAllModesDlgProc,
258 (LPARAM)This) == IDOK)
259 {
260 if (lpPrevSel != This->lpSelDevMode)
261 {
262 (void)PropSheet_Changed(GetParent(This->hwndDlg),
263 This->hwndDlg);
264 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context,
265 This->lpSelDevMode);
266 }
267 }
268 }
269
270 static VOID
271 ShowAdapterProperties(PDESKDISPLAYADAPTER This)
272 {
273 HMODULE hDevMgr;
274 PDEVICEPROPERTIESW pDevicePropertiesW;
275
276 hDevMgr = LoadLibrary(TEXT("devmgr.dll"));
277 if (hDevMgr != NULL)
278 {
279 pDevicePropertiesW = (PDEVICEPROPERTIESW)GetProcAddress(hDevMgr,
280 "DevicePropertiesW");
281 if (pDevicePropertiesW != NULL)
282 {
283 pDevicePropertiesW(This->hwndDlg,
284 NULL,
285 This->lpDeviceId,
286 FALSE);
287 }
288
289 FreeLibrary(hDevMgr);
290 }
291 }
292
293 static VOID
294 InitDisplayAdapterDialog(PDESKDISPLAYADAPTER This)
295 {
296 LPTSTR lpAdapterName;
297
298 This->lpDeviceId = QueryDeskCplString(This->pdtobj,
299 RegisterClipboardFormat(DESK_EXT_DISPLAYID));
300 EnableWindow(GetDlgItem(This->hwndDlg,
301 IDC_ADAPTERPROPERTIES),
302 This->lpDeviceId != NULL && This->lpDeviceId[0] != TEXT('\0'));
303 lpAdapterName = QueryDeskCplString(This->pdtobj,
304 RegisterClipboardFormat(DESK_EXT_DISPLAYNAME));
305 if (lpAdapterName != NULL)
306 {
307 SetDlgItemText(This->hwndDlg,
308 IDC_ADAPTERNAME,
309 lpAdapterName);
310
311 LocalFree((HLOCAL)lpAdapterName);
312 }
313
314 if (This->DeskExtInterface != NULL)
315 {
316 SetDlgItemTextW(This->hwndDlg,
317 IDC_CHIPTYPE,
318 This->DeskExtInterface->ChipType);
319 SetDlgItemTextW(This->hwndDlg,
320 IDC_DACTYPE,
321 This->DeskExtInterface->DacType);
322 SetDlgItemTextW(This->hwndDlg,
323 IDC_MEMORYSIZE,
324 This->DeskExtInterface->MemorySize);
325 SetDlgItemTextW(This->hwndDlg,
326 IDC_ADAPTERSTRING,
327 This->DeskExtInterface->AdapterString);
328 SetDlgItemTextW(This->hwndDlg,
329 IDC_BIOSINFORMATION,
330 This->DeskExtInterface->BiosString);
331
332 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
333 }
334 else
335 This->lpDevModeOnInit = NULL;
336
337 This->lpSelDevMode = This->lpDevModeOnInit;
338 }
339
340 static LONG
341 ApplyDisplayAdapterChanges(PDESKDISPLAYADAPTER This)
342 {
343 LONG lChangeRet;
344
345 if (This->DeskExtInterface != NULL)
346 {
347 /* Change the display settings through desk.cpl */
348 lChangeRet = DeskCplExtDisplaySaveSettings(This->DeskExtInterface,
349 This->hwndDlg);
350 if (lChangeRet == DISP_CHANGE_SUCCESSFUL)
351 {
352 /* Save the new mode */
353 This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
354 This->lpSelDevMode = This->lpDevModeOnInit;
355 return PSNRET_NOERROR;
356 }
357 else if (lChangeRet == DISP_CHANGE_RESTART)
358 {
359 /* Notify desk.cpl that the user needs to reboot */
360 PropSheet_RestartWindows(GetParent(This->hwndDlg));
361 return PSNRET_NOERROR;
362 }
363 }
364
365 return PSNRET_INVALID_NOCHANGEPAGE;
366 }
367
368 static VOID
369 ResetDisplayAdapterChanges(PDESKDISPLAYADAPTER This)
370 {
371 if (This->DeskExtInterface != NULL && This->lpDevModeOnInit != NULL)
372 {
373 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context,
374 This->lpDevModeOnInit);
375 }
376 }
377
378 static INT_PTR CALLBACK
379 DisplayAdapterDlgProc(HWND hwndDlg,
380 UINT uMsg,
381 WPARAM wParam,
382 LPARAM lParam)
383 {
384 PDESKDISPLAYADAPTER This;
385 INT_PTR Ret = 0;
386
387 if (uMsg != WM_INITDIALOG)
388 {
389 This = (PDESKDISPLAYADAPTER)GetWindowLongPtr(hwndDlg,
390 DWL_USER);
391 }
392
393 switch (uMsg)
394 {
395 case WM_INITDIALOG:
396 This = (PDESKDISPLAYADAPTER)((LPCPROPSHEETPAGE)lParam)->lParam;
397 This->hwndDlg = hwndDlg;
398 SetWindowLongPtr(hwndDlg,
399 DWL_USER,
400 (LONG_PTR)This);
401
402 InitDisplayAdapterDialog(This);
403 Ret = TRUE;
404 break;
405
406 case WM_COMMAND:
407 switch (LOWORD(wParam))
408 {
409 case IDC_ADAPTERPROPERTIES:
410 ShowAdapterProperties(This);
411 break;
412
413 case IDC_LISTALLMODES:
414 ShowListAllModes(This);
415 break;
416 }
417
418 break;
419
420 case WM_NOTIFY:
421 {
422 NMHDR *nmh = (NMHDR *)lParam;
423
424 switch (nmh->code)
425 {
426 case PSN_APPLY:
427 {
428 SetWindowLongPtr(hwndDlg,
429 DWL_MSGRESULT,
430 ApplyDisplayAdapterChanges(This));
431 break;
432 }
433
434 case PSN_RESET:
435 ResetDisplayAdapterChanges(This);
436 break;
437 }
438 break;
439 }
440 }
441
442 return Ret;
443 }
444
445 static VOID
446 IDeskDisplayAdapter_Destroy(PDESKDISPLAYADAPTER This)
447 {
448 if (This->pdtobj != NULL)
449 {
450 IDataObject_Release(This->pdtobj);
451 This->pdtobj = NULL;
452 }
453
454 if (This->DeskExtInterface != NULL)
455 {
456 LocalFree((HLOCAL)This->DeskExtInterface);
457 This->DeskExtInterface = NULL;
458 }
459
460 if (This->lpDeviceId != NULL)
461 {
462 LocalFree((HLOCAL)This->lpDeviceId);
463 This->lpDeviceId = NULL;
464 }
465 }
466
467 ULONG
468 IDeskDisplayAdapter_AddRef(PDESKDISPLAYADAPTER This)
469 {
470 ULONG ret;
471
472 ret = InterlockedIncrement((PLONG)&This->ref);
473 if (ret == 1)
474 InterlockedIncrement(&dll_refs);
475
476 return ret;
477 }
478
479 ULONG
480 IDeskDisplayAdapter_Release(PDESKDISPLAYADAPTER This)
481 {
482 ULONG ret;
483
484 ret = InterlockedDecrement((PLONG)&This->ref);
485 if (ret == 0)
486 {
487 IDeskDisplayAdapter_Destroy(This);
488 InterlockedDecrement(&dll_refs);
489
490 HeapFree(GetProcessHeap(),
491 0,
492 This);
493 }
494
495 return ret;
496 }
497
498 HRESULT STDMETHODCALLTYPE
499 IDeskDisplayAdapter_QueryInterface(PDESKDISPLAYADAPTER This,
500 REFIID iid,
501 PVOID *pvObject)
502 {
503 *pvObject = NULL;
504
505 if (IsEqualIID(iid,
506 &IID_IShellPropSheetExt) ||
507 IsEqualIID(iid,
508 &IID_IUnknown))
509 {
510 *pvObject = impl_to_interface(This, IShellPropSheetExt);
511 }
512 else if (IsEqualIID(iid,
513 &IID_IShellExtInit))
514 {
515 *pvObject = impl_to_interface(This, IShellExtInit);
516 }
517 else if (IsEqualIID(iid,
518 &IID_IClassFactory))
519 {
520 *pvObject = impl_to_interface(This, IClassFactory);
521 }
522 else
523 {
524 DPRINT1("IDeskDisplayAdapter::QueryInterface(%p,%p): E_NOINTERFACE\n", iid, pvObject);
525 return E_NOINTERFACE;
526 }
527
528 IDeskDisplayAdapter_AddRef(This);
529 return S_OK;
530 }
531
532 HRESULT
533 IDeskDisplayAdapter_Initialize(PDESKDISPLAYADAPTER This,
534 LPCITEMIDLIST pidlFolder,
535 IDataObject *pdtobj,
536 HKEY hkeyProgID)
537 {
538 DPRINT1("IDeskDisplayAdapter::Initialize(%p,%p,%p)\n", pidlFolder, pdtobj, hkeyProgID);
539
540 if (pdtobj != NULL)
541 {
542 IDataObject_AddRef(pdtobj);
543 This->pdtobj = pdtobj;
544
545 /* Get a copy of the desk.cpl extension interface */
546 This->DeskExtInterface = QueryDeskCplExtInterface(This->pdtobj);
547 if (This->DeskExtInterface != NULL)
548 return S_OK;
549 }
550
551 return S_FALSE;
552 }
553
554 HRESULT
555 IDeskDisplayAdapter_AddPages(PDESKDISPLAYADAPTER This,
556 LPFNADDPROPSHEETPAGE pfnAddPage,
557 LPARAM lParam)
558 {
559 HPROPSHEETPAGE hpsp;
560 PROPSHEETPAGE psp;
561
562 DPRINT1("IDeskDisplayAdapter::AddPages(%p,%p)\n", pfnAddPage, lParam);
563
564 psp.dwSize = sizeof(psp);
565 psp.dwFlags = PSP_DEFAULT;
566 psp.hInstance = hInstance;
567 psp.pszTemplate = MAKEINTRESOURCE(IDD_DISPLAYADAPTER);
568 psp.pfnDlgProc = DisplayAdapterDlgProc;
569 psp.lParam = (LPARAM)This;
570
571 hpsp = CreatePropertySheetPage(&psp);
572 if (hpsp != NULL && pfnAddPage(hpsp, lParam))
573 return S_OK;
574
575 return S_FALSE;
576 }
577
578 HRESULT
579 IDeskDisplayAdapter_ReplacePage(PDESKDISPLAYADAPTER This,
580 EXPPS uPageID,
581 LPFNADDPROPSHEETPAGE pfnReplacePage,
582 LPARAM lParam)
583 {
584 DPRINT1("IDeskDisplayAdapter::ReplacePage(%u,%p,%p)\n", uPageID, pfnReplacePage, lParam);
585 return E_NOTIMPL;
586 }
587
588 HRESULT
589 IDeskDisplayAdapter_Constructor(REFIID riid,
590 LPVOID *ppv)
591 {
592 PDESKDISPLAYADAPTER This;
593 HRESULT hRet = E_OUTOFMEMORY;
594
595 DPRINT1("IDeskDisplayAdapter::Constructor(%p,%p)\n", riid, ppv);
596
597 This = HeapAlloc(GetProcessHeap(),
598 0,
599 sizeof(*This));
600 if (This != NULL)
601 {
602 ZeroMemory(This,
603 sizeof(*This));
604
605 IDeskDisplayAdapter_InitIface(This);
606
607 hRet = IDeskDisplayAdapter_QueryInterface(This,
608 riid,
609 ppv);
610 if (!SUCCEEDED(hRet))
611 IDeskDisplayAdapter_Release(This);
612 }
613
614 return hRet;
615 }
616
617 BOOL WINAPI
618 DllMain(HINSTANCE hinstDLL,
619 DWORD dwReason,
620 LPVOID lpvReserved)
621 {
622 switch (dwReason)
623 {
624 case DLL_PROCESS_ATTACH:
625 hInstance = hinstDLL;
626 DisableThreadLibraryCalls(hInstance);
627 break;
628 }
629
630 return TRUE;
631 }