0b0597701cd42478d9342182e5de147a31f27425
[reactos.git] / reactos / lib / cpl / desk / settings.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Display Control Panel
5 * FILE: lib/cpl/desk/settings.c
6 * PURPOSE: Settings property page
7 *
8 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
9 * Hervé Poussineau (poussine@freesurf.fr)
10 */
11
12 #include <windows.h>
13 #include <commctrl.h>
14 #include <stdio.h>
15 #include <tchar.h>
16 #include <cpl.h>
17
18 #include "resource.h"
19 #include "desk.h"
20
21 /* As slider control can't contain user data, we have to keep an
22 * array of RESOLUTION_INFO to have our own associated data.
23 */
24 typedef struct _RESOLUTION_INFO
25 {
26 DWORD dmPelsWidth;
27 DWORD dmPelsHeight;
28 } RESOLUTION_INFO, *PRESOLUTION_INFO;
29
30 typedef struct _SETTINGS_ENTRY
31 {
32 struct _SETTINGS_ENTRY *Blink;
33 struct _SETTINGS_ENTRY *Flink;
34 DWORD dmBitsPerPel;
35 DWORD dmPelsWidth;
36 DWORD dmPelsHeight;
37 } SETTINGS_ENTRY, *PSETTINGS_ENTRY;
38
39 typedef struct _DISPLAY_DEVICE_ENTRY
40 {
41 struct _DISPLAY_DEVICE_ENTRY *Flink;
42 LPTSTR DeviceDescription;
43 LPTSTR DeviceName;
44 PSETTINGS_ENTRY Settings; /* sorted by increasing dmPelsHeight, BPP */
45 DWORD SettingsCount;
46 PRESOLUTION_INFO Resolutions;
47 DWORD ResolutionsCount;
48 PSETTINGS_ENTRY CurrentSettings; /* Points into Settings list */
49 SETTINGS_ENTRY InitialSettings;
50 } DISPLAY_DEVICE_ENTRY, *PDISPLAY_DEVICE_ENTRY;
51
52 static PDISPLAY_DEVICE_ENTRY DisplayDeviceList = NULL;
53 static PDISPLAY_DEVICE_ENTRY CurrentDisplayDevice = NULL;
54
55 static VOID
56 UpdateDisplay(IN HWND hwndDlg)
57 {
58 TCHAR Buffer[64];
59 TCHAR Pixel[64];
60 DWORD index;
61
62 LoadString(hApplet, IDS_PIXEL, Pixel, sizeof(Pixel) / sizeof(TCHAR));
63 _stprintf(Buffer, Pixel, CurrentDisplayDevice->CurrentSettings->dmPelsWidth, CurrentDisplayDevice->CurrentSettings->dmPelsHeight, Pixel);
64 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT, WM_SETTEXT, 0, (LPARAM)Buffer);
65
66 for (index = 0; index < CurrentDisplayDevice->ResolutionsCount; index++)
67 if (CurrentDisplayDevice->Resolutions[index].dmPelsWidth == CurrentDisplayDevice->CurrentSettings->dmPelsWidth &&
68 CurrentDisplayDevice->Resolutions[index].dmPelsHeight == CurrentDisplayDevice->CurrentSettings->dmPelsHeight)
69 {
70 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETPOS, TRUE, index);
71 break;
72 }
73 if (LoadString(hApplet, (2900 + CurrentDisplayDevice->CurrentSettings->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
74 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SELECTSTRING, -1, (LPARAM)Buffer);
75 }
76
77 static PSETTINGS_ENTRY
78 GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings)
79 {
80 DEVMODE devmode;
81 DWORD NbSettings = 0;
82 DWORD iMode = 0;
83 DWORD dwFlags = 0;
84 PSETTINGS_ENTRY Settings = NULL;
85 HDC hDC;
86 PSETTINGS_ENTRY Current;
87 DWORD bpp, xres, yres;
88
89 /* Get current settings */
90 *CurrentSettings = NULL;
91 hDC = CreateIC(NULL, DeviceName, NULL, NULL);
92 bpp = GetDeviceCaps(hDC, PLANES);
93 bpp *= GetDeviceCaps(hDC, BITSPIXEL);
94 xres = GetDeviceCaps(hDC, HORZRES);
95 yres = GetDeviceCaps(hDC, VERTRES);
96 DeleteDC(hDC);
97
98 /* List all settings */
99 devmode.dmSize = (WORD)sizeof(DEVMODE);
100 devmode.dmDriverExtra = 0;
101 while (EnumDisplaySettingsEx(DeviceName, iMode, &devmode, dwFlags))
102 {
103
104 if (devmode.dmPelsWidth < 640 ||
105 devmode.dmPelsHeight < 480)
106 {
107 iMode++;
108 continue;
109 }
110
111 Current = HeapAlloc(GetProcessHeap(), 0, sizeof(SETTINGS_ENTRY));
112 if (Current != NULL)
113 {
114 /* Sort resolutions by increasing height, and BPP */
115 PSETTINGS_ENTRY Previous = NULL;
116 PSETTINGS_ENTRY Next = Settings;
117 Current->dmPelsWidth = devmode.dmPelsWidth;
118 Current->dmPelsHeight = devmode.dmPelsHeight;
119 Current->dmBitsPerPel = devmode.dmBitsPerPel;
120 while (Next != NULL && (
121 Next->dmPelsHeight < Current->dmPelsHeight ||
122 (Next->dmPelsHeight == Current->dmPelsHeight && Next->dmBitsPerPel < Current->dmBitsPerPel)))
123 {
124 Previous = Next;
125 Next = Next->Flink;
126 }
127 Current->Blink = Previous;
128 Current->Flink = Next;
129 if (Previous == NULL)
130 Settings = Current;
131 else
132 Previous->Flink = Current;
133 if (Next != NULL)
134 Next->Blink = Current;
135 if (devmode.dmPelsWidth == xres && devmode.dmPelsHeight == yres && devmode.dmBitsPerPel == bpp)
136 {
137 *CurrentSettings = Current;
138 }
139 NbSettings++;
140 }
141 iMode++;
142 }
143
144 *pSettingsCount = NbSettings;
145 return Settings;
146 }
147
148 static VOID
149 AddDisplayDevice(IN LPTSTR Description, IN LPTSTR DeviceName)
150 {
151 PDISPLAY_DEVICE_ENTRY newEntry = NULL;
152 LPTSTR description = NULL;
153 LPTSTR name = NULL;
154 DWORD descriptionSize;
155 DWORD nameSize;
156 PSETTINGS_ENTRY Current;
157 DWORD ResolutionsCount = 1;
158 DWORD i;
159
160 newEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(DISPLAY_DEVICE_ENTRY));
161 if (!newEntry) goto ByeBye;
162
163 newEntry->Settings = GetPossibleSettings(DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings);
164 if (!newEntry->Settings) goto ByeBye;
165
166 newEntry->InitialSettings.dmPelsWidth = newEntry->CurrentSettings->dmPelsWidth;
167 newEntry->InitialSettings.dmPelsHeight = newEntry->CurrentSettings->dmPelsHeight;
168 newEntry->InitialSettings.dmBitsPerPel = newEntry->CurrentSettings->dmBitsPerPel;
169
170 /* Count different resolutions */
171 for (Current = newEntry->Settings; Current != NULL; Current = Current->Flink)
172 if (Current->Flink != NULL &&
173 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) || (Current->dmPelsHeight != Current->Flink->dmPelsHeight)))
174 ResolutionsCount++;
175 newEntry->Resolutions = HeapAlloc(GetProcessHeap(), 0, ResolutionsCount * sizeof(RESOLUTION_INFO));
176 if (!newEntry->Resolutions) goto ByeBye;
177 newEntry->ResolutionsCount = ResolutionsCount;
178 /* Fill resolutions infos */
179 for (Current = newEntry->Settings, i = 0; Current != NULL; Current = Current->Flink)
180 if (Current->Flink == NULL || (Current->Flink != NULL &&
181 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) || (Current->dmPelsHeight != Current->Flink->dmPelsHeight))))
182 {
183 newEntry->Resolutions[i].dmPelsWidth = Current->dmPelsWidth;
184 newEntry->Resolutions[i].dmPelsHeight = Current->dmPelsHeight;
185 i++;
186 }
187
188 descriptionSize = (_tcslen(Description) + 1) * sizeof(TCHAR);
189 description = HeapAlloc(GetProcessHeap(), 0, descriptionSize);
190 if (!description) goto ByeBye;
191
192 nameSize = (_tcslen(DeviceName) + 1) * sizeof(TCHAR);
193 name = HeapAlloc(GetProcessHeap(), 0, nameSize);
194 if (!name) goto ByeBye;
195
196 memcpy(description, Description, descriptionSize);
197 memcpy(name, DeviceName, nameSize);
198 newEntry->DeviceDescription = description;
199 newEntry->DeviceName = name;
200 newEntry->Flink = DisplayDeviceList;
201 DisplayDeviceList = newEntry;
202 return;
203
204 ByeBye:
205 if (newEntry != NULL)
206 {
207 if (newEntry->Settings != NULL)
208 {
209 Current = newEntry->Settings;
210 while (Current != NULL)
211 {
212 PSETTINGS_ENTRY Next = Current->Flink;
213 HeapFree(GetProcessHeap(), 0, Current);
214 Current = Next;
215 }
216 }
217 if (newEntry->Resolutions != NULL)
218 HeapFree(GetProcessHeap(), 0, newEntry->Resolutions);
219 HeapFree(GetProcessHeap(), 0, newEntry);
220 }
221 if (description != NULL)
222 HeapFree(GetProcessHeap(), 0, description);
223 if (name != NULL)
224 HeapFree(GetProcessHeap(), 0, name);
225 }
226
227 static VOID
228 OnDisplayDeviceChanged(IN HWND hwndDlg, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
229 {
230 PSETTINGS_ENTRY Current;
231 DWORD index;
232
233 CurrentDisplayDevice = pDeviceEntry; /* Update global variable */
234
235 /* Fill color depths combo box */
236 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_RESETCONTENT, 0, 0);
237 for (Current = pDeviceEntry->Settings; Current != NULL; Current = Current->Flink)
238 {
239 TCHAR Buffer[64];
240 if (LoadString(hApplet, (2900 + Current->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
241 {
242 index = SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
243 if (index == CB_ERR)
244 {
245 index = SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_ADDSTRING, 0, (LPARAM)Buffer);
246 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SETITEMDATA, index, Current->dmBitsPerPel);
247 }
248 }
249 }
250
251 /* Fill resolutions slider */
252 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_CLEARTICS, TRUE, 0);
253 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETRANGE, TRUE, MAKELONG(0, pDeviceEntry->ResolutionsCount - 1));
254
255 UpdateDisplay(hwndDlg);
256 }
257
258 static VOID
259 OnInitDialog(IN HWND hwndDlg)
260 {
261 DWORD Result = 0;
262 DWORD iDevNum = 0;
263 DISPLAY_DEVICE displayDevice;
264
265 /* Get video cards list */
266 displayDevice.cb = (DWORD)sizeof(DISPLAY_DEVICE);
267 while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0))
268 {
269 if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0)
270 {
271 AddDisplayDevice(displayDevice.DeviceString, displayDevice.DeviceName);
272 Result++;
273 }
274 iDevNum++;
275 }
276 if (Result == 0)
277 {
278 /* No adapter found */
279 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_BPP), FALSE);
280 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION), FALSE);
281 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT), FALSE);
282 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_ADVANCED), FALSE);
283 }
284 else if (Result == 1)
285 {
286 /* Single video adapter */
287 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)DisplayDeviceList->DeviceDescription);
288 OnDisplayDeviceChanged(hwndDlg, DisplayDeviceList);
289 }
290 else
291 {
292 /* FIXME: multi video adapter */
293 /* FIXME: choose selected adapter being the primary one */
294 }
295 }
296
297 static VOID
298 OnBPPChanged(IN HWND hwndDlg)
299 {
300 /* if new BPP is not compatible with resolution:
301 * 1) try to find the nearest smaller matching resolution
302 * 2) otherwise, get the nearest bigger resolution
303 */
304 PSETTINGS_ENTRY Current;
305 DWORD dmNewBitsPerPel;
306 DWORD index;
307 TCHAR Buffer[64];
308
309 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, WM_GETTEXT, (WPARAM)(sizeof(Buffer) / sizeof(TCHAR)), (LPARAM)Buffer);
310 index = SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
311 dmNewBitsPerPel = SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
312
313 /* find if new parameters are valid */
314 Current = CurrentDisplayDevice->CurrentSettings;
315 if (dmNewBitsPerPel == Current->dmBitsPerPel)
316 {
317 /* no change */
318 return;
319 }
320
321 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
322
323 if (dmNewBitsPerPel < Current->dmBitsPerPel)
324 {
325 Current = Current->Blink;
326 while (Current != NULL)
327 {
328 if (Current->dmBitsPerPel == dmNewBitsPerPel
329 && Current->dmPelsHeight == CurrentDisplayDevice->CurrentSettings->dmPelsHeight
330 && Current->dmPelsWidth == CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
331 {
332 CurrentDisplayDevice->CurrentSettings = Current;
333 UpdateDisplay(hwndDlg);
334 return;
335 }
336 Current = Current->Blink;
337 }
338 }
339 else
340 {
341 Current = Current->Flink;
342 while (Current != NULL)
343 {
344 if (Current->dmBitsPerPel == dmNewBitsPerPel
345 && Current->dmPelsHeight == CurrentDisplayDevice->CurrentSettings->dmPelsHeight
346 && Current->dmPelsWidth == CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
347 {
348 CurrentDisplayDevice->CurrentSettings = Current;
349 UpdateDisplay(hwndDlg);
350 return;
351 }
352 Current = Current->Flink;
353 }
354 }
355
356 /* search smaller resolution compatible with current color depth */
357 Current = CurrentDisplayDevice->CurrentSettings->Blink;
358 while (Current != NULL)
359 {
360 if (Current->dmBitsPerPel == dmNewBitsPerPel)
361 {
362 CurrentDisplayDevice->CurrentSettings = Current;
363 UpdateDisplay(hwndDlg);
364 return;
365 }
366 Current = Current->Blink;
367 }
368
369 /* search bigger resolution compatible with current color depth */
370 Current = CurrentDisplayDevice->CurrentSettings->Flink;
371 while (Current != NULL)
372 {
373 if (Current->dmBitsPerPel == dmNewBitsPerPel)
374 {
375 CurrentDisplayDevice->CurrentSettings = Current;
376 UpdateDisplay(hwndDlg);
377 return;
378 }
379 Current = Current->Flink;
380 }
381
382 /* we shouldn't go there */
383 }
384
385 static VOID
386 OnResolutionChanged(IN HWND hwndDlg, IN DWORD NewPosition)
387 {
388 /* if new resolution is not compatible with color depth:
389 * 1) try to find the nearest bigger matching color depth
390 * 2) otherwise, get the nearest smaller color depth
391 */
392 PSETTINGS_ENTRY Current;
393 DWORD dmNewPelsHeight = CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
394 DWORD dmNewPelsWidth = CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
395
396 /* find if new parameters are valid */
397 Current = CurrentDisplayDevice->CurrentSettings;
398 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
399 {
400 /* no change */
401 return;
402 }
403
404 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
405
406 if (dmNewPelsHeight < Current->dmPelsHeight)
407 {
408 Current = Current->Blink;
409 while (Current != NULL)
410 {
411 if (Current->dmPelsHeight == dmNewPelsHeight
412 && Current->dmPelsWidth == dmNewPelsWidth
413 && Current->dmBitsPerPel == CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
414 {
415 CurrentDisplayDevice->CurrentSettings = Current;
416 UpdateDisplay(hwndDlg);
417 return;
418 }
419 Current = Current->Blink;
420 }
421 }
422 else
423 {
424 Current = Current->Flink;
425 while (Current != NULL)
426 {
427 if (Current->dmPelsHeight == dmNewPelsHeight
428 && Current->dmPelsWidth == dmNewPelsWidth
429 && Current->dmBitsPerPel == CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
430 {
431 CurrentDisplayDevice->CurrentSettings = Current;
432 UpdateDisplay(hwndDlg);
433 return;
434 }
435 Current = Current->Flink;
436 }
437 }
438
439 /* search bigger color depth compatible with current resolution */
440 Current = CurrentDisplayDevice->CurrentSettings->Flink;
441 while (Current != NULL)
442 {
443 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
444 {
445 CurrentDisplayDevice->CurrentSettings = Current;
446 UpdateDisplay(hwndDlg);
447 return;
448 }
449 Current = Current->Flink;
450 }
451
452 /* search smaller color depth compatible with current resolution */
453 Current = CurrentDisplayDevice->CurrentSettings->Blink;
454 while (Current != NULL)
455 {
456 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
457 {
458 CurrentDisplayDevice->CurrentSettings = Current;
459 UpdateDisplay(hwndDlg);
460 return;
461 }
462 Current = Current->Blink;
463 }
464
465 /* we shouldn't go there */
466 }
467
468 static VOID
469 OnAdvancedButton()
470 {
471 MessageBox(NULL, TEXT("That button doesn't do anything yet"), TEXT("Whoops"), MB_OK);
472 }
473
474 /* Property page dialog callback */
475 INT_PTR CALLBACK
476 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
477 {
478 switch(uMsg)
479 {
480 case WM_INITDIALOG:
481 OnInitDialog(hwndDlg);
482 break;
483 case WM_COMMAND:
484 {
485 DWORD controlId = LOWORD(wParam);
486 DWORD command = HIWORD(wParam);
487
488 if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
489 OnAdvancedButton();
490 else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
491 OnBPPChanged(hwndDlg);
492 break;
493 }
494 case WM_HSCROLL:
495 {
496 switch (LOWORD(wParam))
497 {
498 case TB_LINEUP:
499 case TB_LINEDOWN:
500 case TB_PAGEUP:
501 case TB_PAGEDOWN:
502 case TB_TOP:
503 case TB_BOTTOM:
504 case TB_ENDTRACK:
505 {
506 DWORD newPosition = SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
507 OnResolutionChanged(hwndDlg, newPosition);
508 }
509 }
510 break;
511 }
512 case WM_NOTIFY:
513 {
514 LPNMHDR lpnm = (LPNMHDR)lParam;
515 if (lpnm->code == PSN_APPLY)
516 {
517 if (CurrentDisplayDevice->CurrentSettings->dmPelsWidth != CurrentDisplayDevice->InitialSettings.dmPelsWidth
518 || CurrentDisplayDevice->CurrentSettings->dmPelsHeight != CurrentDisplayDevice->InitialSettings.dmPelsHeight
519 || CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
520 {
521 /* FIXME: Need to test changes */
522 /* Apply new settings */
523 LONG rc;
524 DEVMODE devmode;
525 RtlZeroMemory(&devmode, sizeof(DEVMODE));
526 devmode.dmSize = (WORD)sizeof(DEVMODE);
527 devmode.dmPelsWidth = CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
528 devmode.dmPelsHeight = CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
529 devmode.dmBitsPerPel = CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
530 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
531 rc = ChangeDisplaySettingsEx(
532 CurrentDisplayDevice->DeviceName,
533 &devmode,
534 NULL,
535 CDS_UPDATEREGISTRY,
536 NULL);
537 switch (rc)
538 {
539 case DISP_CHANGE_SUCCESSFUL:
540 CurrentDisplayDevice->InitialSettings.dmPelsWidth = CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
541 CurrentDisplayDevice->InitialSettings.dmPelsHeight = CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
542 CurrentDisplayDevice->InitialSettings.dmBitsPerPel = CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
543 break;
544 case DISP_CHANGE_FAILED:
545 MessageBox(NULL, TEXT("Failed to apply new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
546 break;
547 case DISP_CHANGE_RESTART:
548 MessageBox(NULL, TEXT("You need to restart your computer to apply changes."), TEXT("Display settings"), MB_OK | MB_ICONINFORMATION);
549 break;
550 default:
551 MessageBox(NULL, TEXT("Unknown error when applying new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
552 break;
553 }
554 }
555 }
556 break;
557 }
558 case WM_DESTROY:
559 {
560 PDISPLAY_DEVICE_ENTRY Current = DisplayDeviceList;
561 while (Current != NULL)
562 {
563 PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
564 PSETTINGS_ENTRY CurrentSettings = Current->Settings;
565 while (CurrentSettings != NULL)
566 {
567 PSETTINGS_ENTRY NextSettings = CurrentSettings->Flink;
568 HeapFree(GetProcessHeap(), 0, CurrentSettings);
569 CurrentSettings = NextSettings;
570 }
571 HeapFree(GetProcessHeap(), 0, Current);
572 Current = Next;
573 }
574 }
575 }
576 return FALSE;
577 }