VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxControl/VBoxControl.cpp@ 4968

Last change on this file since 4968 was 4968, checked in by vboxsync, 17 years ago

Implemented VBoxControl setvideomode command for Windows guest additions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.9 KB
Line 
1/** @file
2 *
3 * VBoxControl - Guest Additions Utility
4 *
5 * Copyright (C) 2006-2007 innotek GmbH
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License as published by the Free Software Foundation,
11 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
12 * distribution. VirtualBox OSE is distributed in the hope that it will
13 * be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15
16#include <windows.h>
17#include <stdio.h>
18#include <stdarg.h>
19#include <malloc.h>
20
21void printHelp()
22{
23 printf("VBoxControl getvideoacceleration\n"
24 "\n"
25 "VBoxControl setvideoacceleration <on|off>\n"
26 "\n"
27 "VBoxControl listcustommodes\n"
28 "\n"
29 "VBoxControl addcustommode <width> <height> <bpp>\n"
30 "\n"
31 "VBoxControl removecustommode <width> <height> <bpp>\n"
32 "\n"
33 "VBoxControl setvideomode <width> <height> <bpp> <screen>\n");
34}
35
36#if defined(DEBUG) || defined(LOG_ENABLED)
37#define dprintf(a) do { int err = GetLastError (); printf a; SetLastError (err); } while (0)
38#else
39#define dprintf(a) do {} while (0)
40#endif /* DEBUG */
41
42LONG (WINAPI * gpfnChangeDisplaySettingsEx)(LPCTSTR lpszDeviceName, LPDEVMODE lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam);
43
44static unsigned nextAdjacentRectXP (RECTL *paRects, unsigned nRects, unsigned iRect)
45{
46 unsigned i;
47 for (i = 0; i < nRects; i++)
48 {
49 if (paRects[iRect].right == paRects[i].left)
50 {
51 return i;
52 }
53 }
54 return ~0;
55}
56
57static unsigned nextAdjacentRectXN (RECTL *paRects, unsigned nRects, unsigned iRect)
58{
59 unsigned i;
60 for (i = 0; i < nRects; i++)
61 {
62 if (paRects[iRect].left == paRects[i].right)
63 {
64 return i;
65 }
66 }
67 return ~0;
68}
69
70static unsigned nextAdjacentRectYP (RECTL *paRects, unsigned nRects, unsigned iRect)
71{
72 unsigned i;
73 for (i = 0; i < nRects; i++)
74 {
75 if (paRects[iRect].bottom == paRects[i].top)
76 {
77 return i;
78 }
79 }
80 return ~0;
81}
82
83unsigned nextAdjacentRectYN (RECTL *paRects, unsigned nRects, unsigned iRect)
84{
85 unsigned i;
86 for (i = 0; i < nRects; i++)
87 {
88 if (paRects[iRect].top == paRects[i].bottom)
89 {
90 return i;
91 }
92 }
93 return ~0;
94}
95
96void resizeRect(RECTL *paRects, unsigned nRects, unsigned iPrimary, unsigned iResized, int NewWidth, int NewHeight)
97{
98 RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects);
99 memcpy (paNewRects, paRects, sizeof (RECTL) * nRects);
100 paNewRects[iResized].right += NewWidth - (paNewRects[iResized].right - paNewRects[iResized].left);
101 paNewRects[iResized].bottom += NewHeight - (paNewRects[iResized].bottom - paNewRects[iResized].top);
102
103 /* Verify all pairs of originally adjacent rectangles for all 4 directions.
104 * If the pair has a "good" delta (that is the first rectangle intersects the second)
105 * at a direction and the second rectangle is not primary one (which can not be moved),
106 * move the second rectangle to make it adjacent to the first one.
107 */
108
109 /* X positive. */
110 unsigned iRect;
111 for (iRect = 0; iRect < nRects; iRect++)
112 {
113 /* Find the next adjacent original rect in x positive direction. */
114 unsigned iNextRect = nextAdjacentRectXP (paRects, nRects, iRect);
115 dprintf(("next %d -> %d\n", iRect, iNextRect));
116
117 if (iNextRect == ~0 || iNextRect == iPrimary)
118 {
119 continue;
120 }
121
122 /* Check whether there is an X intesection between these adjacent rects in the new rectangles
123 * and fix the intersection if delta is "good".
124 */
125 int delta = paNewRects[iRect].right - paNewRects[iNextRect].left;
126
127 if (delta > 0)
128 {
129 dprintf(("XP intersection right %d left %d, diff %d\n",
130 paNewRects[iRect].right, paNewRects[iNextRect].left,
131 delta));
132
133 paNewRects[iNextRect].left += delta;
134 paNewRects[iNextRect].right += delta;
135 }
136 }
137
138 /* X negative. */
139 for (iRect = 0; iRect < nRects; iRect++)
140 {
141 /* Find the next adjacent original rect in x negative direction. */
142 unsigned iNextRect = nextAdjacentRectXN (paRects, nRects, iRect);
143 dprintf(("next %d -> %d\n", iRect, iNextRect));
144
145 if (iNextRect == ~0 || iNextRect == iPrimary)
146 {
147 continue;
148 }
149
150 /* Check whether there is an X intesection between these adjacent rects in the new rectangles
151 * and fix the intersection if delta is "good".
152 */
153 int delta = paNewRects[iRect].left - paNewRects[iNextRect].right;
154
155 if (delta < 0)
156 {
157 dprintf(("XN intersection left %d right %d, diff %d\n",
158 paNewRects[iRect].left, paNewRects[iNextRect].right,
159 delta));
160
161 paNewRects[iNextRect].left += delta;
162 paNewRects[iNextRect].right += delta;
163 }
164 }
165
166 /* Y positive (in the computer sence, top->down). */
167 for (iRect = 0; iRect < nRects; iRect++)
168 {
169 /* Find the next adjacent original rect in y positive direction. */
170 unsigned iNextRect = nextAdjacentRectYP (paRects, nRects, iRect);
171 dprintf(("next %d -> %d\n", iRect, iNextRect));
172
173 if (iNextRect == ~0 || iNextRect == iPrimary)
174 {
175 continue;
176 }
177
178 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles
179 * and fix the intersection if delta is "good".
180 */
181 int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top;
182
183 if (delta > 0)
184 {
185 dprintf(("YP intersection bottom %d top %d, diff %d\n",
186 paNewRects[iRect].bottom, paNewRects[iNextRect].top,
187 delta));
188
189 paNewRects[iNextRect].top += delta;
190 paNewRects[iNextRect].bottom += delta;
191 }
192 }
193
194 /* Y negative (in the computer sence, down->top). */
195 for (iRect = 0; iRect < nRects; iRect++)
196 {
197 /* Find the next adjacent original rect in x negative direction. */
198 unsigned iNextRect = nextAdjacentRectYN (paRects, nRects, iRect);
199 dprintf(("next %d -> %d\n", iRect, iNextRect));
200
201 if (iNextRect == ~0 || iNextRect == iPrimary)
202 {
203 continue;
204 }
205
206 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles
207 * and fix the intersection if delta is "good".
208 */
209 int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom;
210
211 if (delta < 0)
212 {
213 dprintf(("YN intersection top %d bottom %d, diff %d\n",
214 paNewRects[iRect].top, paNewRects[iNextRect].bottom,
215 delta));
216
217 paNewRects[iNextRect].top += delta;
218 paNewRects[iNextRect].bottom += delta;
219 }
220 }
221
222 memcpy (paRects, paNewRects, sizeof (RECTL) * nRects);
223 return;
224}
225
226/* Returns TRUE to try again. */
227static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
228{
229 BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0);
230
231 DISPLAY_DEVICE DisplayDevice;
232
233 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
234 DisplayDevice.cb = sizeof(DisplayDevice);
235
236 /* Find out how many display devices the system has */
237 DWORD NumDevices = 0;
238 DWORD i = 0;
239 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
240 {
241 dprintf(("[%d] %s\n", i, DisplayDevice.DeviceName));
242
243 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
244 {
245 dprintf(("Found primary device. err %d\n", GetLastError ()));
246 NumDevices++;
247 }
248 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
249 {
250
251 dprintf(("Found secondary device. err %d\n", GetLastError ()));
252 NumDevices++;
253 }
254
255 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
256 DisplayDevice.cb = sizeof(DisplayDevice);
257 i++;
258 }
259
260 dprintf(("Found total %d devices. err %d\n", NumDevices, GetLastError ()));
261
262 if (NumDevices == 0 || Id >= NumDevices)
263 {
264 dprintf(("Requested identifier %d is invalid. err %d\n", Id, GetLastError ()));
265 return FALSE;
266 }
267
268 DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
269 DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
270 RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices);
271
272 /* Fetch information about current devices and modes. */
273 DWORD DevNum = 0;
274 DWORD DevPrimaryNum = 0;
275
276 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
277 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
278
279 i = 0;
280 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
281 {
282 dprintf(("[%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName));
283
284 BOOL bFetchDevice = FALSE;
285
286 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
287 {
288 dprintf(("Found primary device. err %d\n", GetLastError ()));
289 DevPrimaryNum = DevNum;
290 bFetchDevice = TRUE;
291 }
292 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
293 {
294
295 dprintf(("Found secondary device. err %d\n", GetLastError ()));
296 bFetchDevice = TRUE;
297 }
298
299 if (bFetchDevice)
300 {
301 if (DevNum >= NumDevices)
302 {
303 dprintf(("%d >= %d\n", NumDevices, DevNum));
304 return FALSE;
305 }
306
307 paDisplayDevices[DevNum] = DisplayDevice;
308
309 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
310 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE);
311 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
312 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum]))
313 {
314 dprintf(("EnumDisplaySettings err %d\n", GetLastError ()));
315 return FALSE;
316 }
317
318 dprintf(("%dx%d at %d,%d\n",
319 paDeviceModes[DevNum].dmPelsWidth,
320 paDeviceModes[DevNum].dmPelsHeight,
321 paDeviceModes[DevNum].dmPosition.x,
322 paDeviceModes[DevNum].dmPosition.y));
323
324 paRects[DevNum].left = paDeviceModes[DevNum].dmPosition.x;
325 paRects[DevNum].top = paDeviceModes[DevNum].dmPosition.y;
326 paRects[DevNum].right = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
327 paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
328 DevNum++;
329 }
330
331 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
332 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
333 i++;
334 }
335
336 if (Width == 0)
337 {
338 Width = paRects[Id].right - paRects[Id].left;
339 }
340
341 if (Height == 0)
342 {
343 Height = paRects[Id].bottom - paRects[Id].top;
344 }
345
346 /* Check whether a mode reset or a change is requested. */
347 if ( !fModeReset
348 && paRects[Id].right - paRects[Id].left == Width
349 && paRects[Id].bottom - paRects[Id].top == Height
350 && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel)
351 {
352 dprintf(("VBoxDisplayThread : already at desired resolution.\n"));
353 return FALSE;
354 }
355
356 resizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height);
357#ifdef dprintf
358 for (i = 0; i < NumDevices; i++)
359 {
360 dprintf(("[%d]: %d,%d %dx%d\n",
361 i, paRects[i].left, paRects[i].top,
362 paRects[i].right - paRects[i].left,
363 paRects[i].bottom - paRects[i].top));
364 }
365#endif /* dprintf */
366
367 /* Without this, Windows will not ask the miniport for its
368 * mode table but uses an internal cache instead.
369 */
370 DEVMODE tempDevMode;
371 ZeroMemory (&tempDevMode, sizeof (tempDevMode));
372 tempDevMode.dmSize = sizeof(DEVMODE);
373 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode);
374
375 /* Assign the new rectangles to displays. */
376 for (i = 0; i < NumDevices; i++)
377 {
378 paDeviceModes[i].dmPosition.x = paRects[i].left;
379 paDeviceModes[i].dmPosition.y = paRects[i].top;
380 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left;
381 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top;
382
383 paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH;
384
385 if ( i == Id
386 && BitsPerPixel != 0)
387 {
388 paDeviceModes[i].dmFields |= DM_BITSPERPEL;
389 paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
390 }
391 dprintf(("calling pfnChangeDisplaySettingsEx %x\n", gpfnChangeDisplaySettingsEx));
392 gpfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
393 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
394 dprintf(("ChangeDisplaySettings position err %d\n", GetLastError ()));
395 }
396
397 /* A second call to ChangeDisplaySettings updates the monitor. */
398 LONG status = ChangeDisplaySettings(NULL, 0);
399 dprintf(("ChangeDisplaySettings update status %d\n", status));
400 if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE)
401 {
402 /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
403 return FALSE;
404 }
405
406 /* Retry the request. */
407 return TRUE;
408}
409
410void handleSetVideoMode(int argc, char *argv[])
411{
412 if (argc != 3 && argc != 4)
413 {
414 printf("Error: not enough parameters!\n");
415 return;
416 }
417
418 DWORD xres = atoi(argv[0]);
419 DWORD yres = atoi(argv[1]);
420 DWORD bpp = atoi(argv[2]);
421 DWORD scr = 0;
422
423 if (argc == 4)
424 {
425 scr = atoi(argv[3]);
426 }
427
428 HMODULE hUser = GetModuleHandle("USER32");
429
430 if (hUser)
431 {
432 *(uintptr_t *)&gpfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
433 dprintf(("VBoxService: pChangeDisplaySettingsEx = %p\n", gpfnChangeDisplaySettingsEx));
434
435 if (gpfnChangeDisplaySettingsEx)
436 {
437 /* The screen index is 0 based in the ResizeDisplayDevice call. */
438 scr = scr > 0? scr - 1: 0;
439
440 /* Horizontal resolution must be a multiple of 8, round down. */
441 xres &= ~0x7;
442
443 ResizeDisplayDevice(scr, xres, yres, bpp);
444 }
445 }
446}
447
448HKEY getVideoKey(bool writable)
449{
450 HKEY hkeyDeviceMap = 0;
451 HKEY hkeyVideo = 0;
452 LONG status;
453
454 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkeyDeviceMap);
455 if ((status != ERROR_SUCCESS) || !hkeyDeviceMap)
456 {
457 printf("Error opening video device map registry key!\n");
458 return 0;
459 }
460 char szVideoLocation[256];
461 DWORD dwKeyType;
462 szVideoLocation[0] = 0;
463 DWORD len = sizeof(szVideoLocation);
464 status = RegQueryValueExA(hkeyDeviceMap, "\\Device\\Video0", NULL, &dwKeyType, (LPBYTE)szVideoLocation, &len);
465 /*
466 * This value will start with a weird value: \REGISTRY\Machine
467 * Make sure this is true.
468 */
469 if ( (status == ERROR_SUCCESS)
470 && (dwKeyType == REG_SZ)
471 && (_strnicmp(szVideoLocation, "\\REGISTRY\\Machine", 17) == 0))
472 {
473 /* open that branch */
474 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, &szVideoLocation[18], 0, KEY_READ | (writable ? KEY_WRITE : 0), &hkeyVideo);
475 }
476 else
477 {
478 printf("Error opening registry key '%s'\n", &szVideoLocation[18]);
479 }
480 RegCloseKey(hkeyDeviceMap);
481 return hkeyVideo;
482}
483
484void handleGetVideoAcceleration(int argc, char *argv[])
485{
486 ULONG status;
487 HKEY hkeyVideo = getVideoKey(false);
488
489 if (hkeyVideo)
490 {
491 /* query the actual value */
492 DWORD fAcceleration = 1;
493 DWORD len = sizeof(fAcceleration);
494 DWORD dwKeyType;
495 status = RegQueryValueExA(hkeyVideo, "EnableVideoAccel", NULL, &dwKeyType, (LPBYTE)&fAcceleration, &len);
496 if (status != ERROR_SUCCESS)
497 printf("Video acceleration: default\n");
498 else
499 printf("Video acceleration: %s\n", fAcceleration ? "on" : "off");
500 RegCloseKey(hkeyVideo);
501 }
502}
503
504void handleSetVideoAcceleration(int argc, char *argv[])
505{
506 ULONG status;
507 HKEY hkeyVideo;
508
509 /* must have exactly one argument: the new offset */
510 if ( (argc != 1)
511 || ( strcmp(argv[0], "on")
512 && strcmp(argv[0], "off")))
513 {
514 printf("Error: invalid video acceleration status!\n");
515 return;
516 }
517
518 hkeyVideo = getVideoKey(true);
519
520 if (hkeyVideo)
521 {
522 int fAccel = 0;
523 if (!strcmp(argv[0], "on"))
524 fAccel = 1;
525 /* set a new value */
526 status = RegSetValueExA(hkeyVideo, "EnableVideoAccel", 0, REG_DWORD, (LPBYTE)&fAccel, sizeof(fAccel));
527 if (status != ERROR_SUCCESS)
528 {
529 printf("Error %d writing video acceleration status!\n", status);
530 }
531 RegCloseKey(hkeyVideo);
532 }
533}
534
535#define MAX_CUSTOM_MODES 128
536
537/* the table of custom modes */
538struct
539{
540 DWORD xres;
541 DWORD yres;
542 DWORD bpp;
543} customModes[MAX_CUSTOM_MODES] = {0};
544
545void getCustomModes(HKEY hkeyVideo)
546{
547 ULONG status;
548 int curMode = 0;
549
550 /* null out the table */
551 memset(customModes, 0, sizeof(customModes));
552
553 do
554 {
555 char valueName[20];
556 DWORD xres, yres, bpp = 0;
557 DWORD dwType;
558 DWORD dwLen = sizeof(DWORD);
559
560 sprintf(valueName, "CustomMode%dWidth", curMode);
561 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&xres, &dwLen);
562 if (status != ERROR_SUCCESS)
563 break;
564 sprintf(valueName, "CustomMode%dHeight", curMode);
565 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&yres, &dwLen);
566 if (status != ERROR_SUCCESS)
567 break;
568 sprintf(valueName, "CustomMode%dBPP", curMode);
569 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&bpp, &dwLen);
570 if (status != ERROR_SUCCESS)
571 break;
572
573 /* check if the mode is OK */
574 if ( (xres > (1 << 16))
575 && (yres > (1 << 16))
576 && ( (bpp != 16)
577 || (bpp != 24)
578 || (bpp != 32)))
579 break;
580
581 /* add mode to table */
582 customModes[curMode].xres = xres;
583 customModes[curMode].yres = yres;
584 customModes[curMode].bpp = bpp;
585
586 ++curMode;
587
588 if (curMode >= MAX_CUSTOM_MODES)
589 break;
590 } while(1);
591}
592
593void writeCustomModes(HKEY hkeyVideo)
594{
595 ULONG status;
596 int tableIndex = 0;
597 int modeIndex = 0;
598
599 /* first remove all values */
600 for (int i = 0; i < MAX_CUSTOM_MODES; i++)
601 {
602 char valueName[20];
603 sprintf(valueName, "CustomMode%dWidth", i);
604 RegDeleteValueA(hkeyVideo, valueName);
605 sprintf(valueName, "CustomMode%dHeight", i);
606 RegDeleteValueA(hkeyVideo, valueName);
607 sprintf(valueName, "CustomMode%dBPP", i);
608 RegDeleteValueA(hkeyVideo, valueName);
609 }
610
611 do
612 {
613 if (tableIndex >= MAX_CUSTOM_MODES)
614 break;
615
616 /* is the table entry present? */
617 if ( (!customModes[tableIndex].xres)
618 || (!customModes[tableIndex].yres)
619 || (!customModes[tableIndex].bpp))
620 {
621 tableIndex++;
622 continue;
623 }
624
625 printf("writing mode %d (%dx%dx%d)\n", modeIndex, customModes[tableIndex].xres, customModes[tableIndex].yres, customModes[tableIndex].bpp);
626 char valueName[20];
627 sprintf(valueName, "CustomMode%dWidth", modeIndex);
628 status = RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].xres,
629 sizeof(customModes[tableIndex].xres));
630 sprintf(valueName, "CustomMode%dHeight", modeIndex);
631 RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].yres,
632 sizeof(customModes[tableIndex].yres));
633 sprintf(valueName, "CustomMode%dBPP", modeIndex);
634 RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].bpp,
635 sizeof(customModes[tableIndex].bpp));
636
637 modeIndex++;
638 tableIndex++;
639
640 } while(1);
641
642}
643
644void handleListCustomModes(int argc, char *argv[])
645{
646 if (argc != 0)
647 {
648 printf("Error: too many parameters!");
649 return;
650 }
651
652 HKEY hkeyVideo = getVideoKey(false);
653
654 if (hkeyVideo)
655 {
656 getCustomModes(hkeyVideo);
657 for (int i = 0; i < (sizeof(customModes) / sizeof(customModes[0])); i++)
658 {
659 if ( !customModes[i].xres
660 || !customModes[i].yres
661 || !customModes[i].bpp)
662 continue;
663
664 printf("Mode: %d x %d x %d\n",
665 customModes[i].xres, customModes[i].yres, customModes[i].bpp);
666 }
667 RegCloseKey(hkeyVideo);
668 }
669}
670
671void handleAddCustomMode(int argc, char *argv[])
672{
673 if (argc != 3)
674 {
675 printf("Error: not enough parameters!\n");
676 return;
677 }
678
679 DWORD xres = atoi(argv[0]);
680 DWORD yres = atoi(argv[1]);
681 DWORD bpp = atoi(argv[2]);
682
683 /** @todo better check including xres mod 8 = 0! */
684 if ( (xres > (1 << 16))
685 && (yres > (1 << 16))
686 && ( (bpp != 16)
687 || (bpp != 24)
688 || (bpp != 32)))
689 {
690 printf("Error: invalid mode specified!\n");
691 return;
692 }
693
694 HKEY hkeyVideo = getVideoKey(true);
695
696 if (hkeyVideo)
697 {
698 getCustomModes(hkeyVideo);
699 for (int i = 0; i < MAX_CUSTOM_MODES; i++)
700 {
701 /* item free? */
702 if (!customModes[i].xres)
703 {
704 customModes[i].xres = xres;
705 customModes[i].yres = yres;
706 customModes[i].bpp = bpp;
707 break;
708 }
709 }
710 writeCustomModes(hkeyVideo);
711 RegCloseKey(hkeyVideo);
712 }
713}
714
715void handleRemoveCustomMode(int argc, char *argv[])
716{
717 if (argc != 3)
718 {
719 printf("Error: not enough parameters!\n");
720 return;
721 }
722
723 DWORD xres = atoi(argv[0]);
724 DWORD yres = atoi(argv[1]);
725 DWORD bpp = atoi(argv[2]);
726
727 HKEY hkeyVideo = getVideoKey(true);
728
729 if (hkeyVideo)
730 {
731 getCustomModes(hkeyVideo);
732 for (int i = 0; i < MAX_CUSTOM_MODES; i++)
733 {
734 /* correct item? */
735 if ( (customModes[i].xres == xres)
736 && (customModes[i].yres == yres)
737 && (customModes[i].bpp == bpp))
738 {
739printf("found mode at index %d\n", i);
740 memset(&customModes[i], 0, sizeof(customModes[i]));
741 break;
742 }
743 }
744 writeCustomModes(hkeyVideo);
745 RegCloseKey(hkeyVideo);
746 }
747}
748
749
750/**
751 * Main function
752 */
753int main(int argc, char *argv[])
754{
755 if (argc < 2)
756 {
757 printHelp();
758 return 1;
759 }
760
761 /* determine which command */
762 if (strcmp(argv[1], "getvideoacceleration") == 0)
763 {
764 handleGetVideoAcceleration(argc - 2, &argv[2]);
765 }
766 else if (strcmp(argv[1], "setvideoacceleration") == 0)
767 {
768 handleSetVideoAcceleration(argc - 2, &argv[2]);
769 }
770 else if (strcmp(argv[1], "listcustommodes") == 0)
771 {
772 handleListCustomModes(argc - 2, &argv[2]);
773 }
774 else if (strcmp(argv[1], "addcustommode") == 0)
775 {
776 handleAddCustomMode(argc - 2, &argv[2]);
777 }
778 else if (strcmp(argv[1], "removecustommode") == 0)
779 {
780 handleRemoveCustomMode(argc - 2, &argv[2]);
781 }
782 else if (strcmp(argv[1], "setvideomode") == 0)
783 {
784 handleSetVideoMode(argc - 2, &argv[2]);
785 }
786 else
787 {
788 printHelp();
789 return 1;
790 }
791
792 return 0;
793}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette