Sync with trunk head (part 1 of x)
[reactos.git] / dll / shellext / deskadp / deskadp.c
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 }