Changeset 10797
- Timestamp:
- 07/22/08 10:12:42 (3 months ago)
- Files:
-
- trunk/Config.kmk (modified) (1 diff)
- trunk/include/VBox/HostServices/GuestPropertySvc.h (moved) (moved from trunk/include/VBox/HostServices/VBoxInfoSvc.h) (7 diffs)
- trunk/include/VBox/VBoxGuest.h (modified) (1 diff)
- trunk/src/VBox/Additions/WINNT/Makefile.kmk (modified) (1 diff)
- trunk/src/VBox/Additions/WINNT/VBoxControl (deleted)
- trunk/src/VBox/Additions/common/Makefile.kmk (modified) (1 diff)
- trunk/src/VBox/Additions/common/VBoxControl/Makefile.kmk (modified) (1 diff)
- trunk/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp (modified) (11 diffs)
- trunk/src/VBox/Additions/common/VBoxControl/VBoxControl.rc (added)
- trunk/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk (modified) (4 diffs)
- trunk/src/VBox/Additions/common/VBoxGuestLib/VBGLR3Internal.h (modified) (1 diff)
- trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp (moved) (moved from trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibInfoSvc.cpp) (10 diffs)
- trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibVideo.cpp (modified) (8 diffs)
- trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk (modified) (1 diff)
- trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp (modified) (7 diffs)
- trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h (modified) (1 diff)
- trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp (modified) (1 diff)
- trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp (modified) (1 diff)
- trunk/src/VBox/Frontends/VirtualBox4/src/VBoxGlobal.cpp (modified) (1 diff)
- trunk/src/VBox/HostServices/GuestProperties (moved) (moved from trunk/src/VBox/HostServices/SharedInfoServices)
- trunk/src/VBox/HostServices/GuestProperties/Makefile.kmk (copied) (copied from trunk/src/VBox/HostServices/SharedInfoServices/Makefile.kmk) (1 diff)
- trunk/src/VBox/HostServices/GuestProperties/noncopyable.h (copied) (copied from trunk/src/VBox/HostServices/SharedInfoServices/noncopyable.h) (2 diffs)
- trunk/src/VBox/HostServices/GuestProperties/service.cpp (copied) (copied from trunk/src/VBox/HostServices/SharedInfoServices/service.cpp) (11 diffs)
- trunk/src/VBox/HostServices/Makefile.kmk (modified) (1 diff)
- trunk/src/VBox/Installer/linux/Makefile.kmk (modified) (1 diff)
- trunk/src/VBox/Installer/solaris/Makefile.kmk (modified) (3 diffs)
- trunk/src/VBox/Main/ConsoleImpl.cpp (modified) (14 diffs)
- trunk/src/VBox/Main/ConsoleImpl2.cpp (modified) (5 diffs)
- trunk/src/VBox/Main/MachineImpl.cpp (modified) (6 diffs)
- trunk/src/VBox/Main/Makefile.kmk (modified) (1 diff)
- trunk/src/VBox/Main/SessionImpl.cpp (modified) (2 diffs)
- trunk/src/VBox/Main/idl/VirtualBox.xidl (modified) (7 diffs)
- trunk/src/VBox/Main/include/MachineImpl.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Config.kmk
r10773 r10797 320 320 endif 321 321 # Enable the host/guest information service (aka guest properties). 322 VBOX_WITH_ INFO_SVC= 1322 VBOX_WITH_GUEST_PROPS = 1 323 323 # Enable performance API. 324 324 VBOX_WITH_RESOURCE_USAGE_API = 1 trunk/include/VBox/HostServices/GuestPropertySvc.h
r10003 r10797 1 1 /** @file 2 * Shared information services:2 * Guest property service: 3 3 * Common header for host service and guest clients. 4 4 */ … … 20 20 */ 21 21 22 #ifndef ___VBox_HostService_ VBoxSharedInfoSvc_h23 #define ___VBox_HostService_ VBoxSharedInfoSvc_h22 #ifndef ___VBox_HostService_GuestPropertyService_h 23 #define ___VBox_HostService_GuestPropertyService_h 24 24 25 25 #include <VBox/types.h> … … 28 28 29 29 /** Everything defined in this file lives in this namespace. */ 30 namespace svcInfo{30 namespace guestProp { 31 31 32 32 /* … … 35 35 enum eHostFn 36 36 { 37 /** Pass the address of the c onsole object from Main to the service*/37 /** Pass the address of the cfgm node used by the service as a database. */ 38 38 SET_CFGM_NODE = 1, 39 39 /** … … 60 60 enum eGuestFn 61 61 { 62 /** Get the value attached to a configuration property key */ 63 GET_CONFIG_KEY = 1, 64 /** Set the value attached to a configuration property key */ 65 SET_CONFIG_KEY = 2, 66 /** Remove the value attached to a configuration property key */ 67 DEL_CONFIG_KEY = 3 62 /** Get a guest property */ 63 GET_PROP = 1, 64 /** Set a guest property */ 65 SET_PROP = 2, 66 /** Set just the value of a guest property */ 67 SET_PROP_VALUE = 3, 68 /** Delete a guest property */ 69 DEL_PROP = 4, 70 /** Enumerate guest properties */ 71 ENUM_PROPS = 5 68 72 }; 69 73 … … 72 76 /** Helper macro for the length of the prefix VBOX_SHARED_INFO_KEY_PREFIX */ 73 77 #define VBOX_SHARED_INFO_PREFIX_LEN (sizeof(VBOX_SHARED_INFO_KEY_PREFIX) - 1) 74 /** Maximum length for extra data keys used by the get and set key value functions */ 75 enum { KEY_MAX_LEN = 64 }; 78 /** Maximum length for property names */ 79 enum { MAX_NAME_LEN = 64 }; 80 /** Maximum length for property values */ 81 enum { MAX_VALUE_LEN = 128 }; 76 82 /** Maximum length for extra data key values used by the get and set key value functions */ 77 enum { KEY_MAX_VALUE_LEN = 128 };78 /** Maximum number of extra data keys per guest */79 enum { KEY_MAX_KEYS = 256 };83 enum { MAX_FLAGS_LEN = 128 }; 84 /** Maximum number of properties per guest */ 85 enum { MAX_KEYS = 256 }; 80 86 81 87 /** … … 83 89 */ 84 90 #pragma pack (1) 85 /** The guest is requesting the value of a configuration key */86 typedef struct _Get ConfigKey87 { 88 VBoxGuestHGCMCallInfo hdr; 89 90 /** 91 * The key to look up(IN pointer)91 /** The guest is requesting the value of a property */ 92 typedef struct _GetProperty 93 { 94 VBoxGuestHGCMCallInfo hdr; 95 96 /** 97 * The property name (IN pointer) 92 98 * This must fit to a number of criteria, namely 93 * - Only ASCII characters with no spaces 94 * - Less than or equal to VBOX_SHARED_INFO_KEY_MAX_LEN bytes in length 95 * - Zero terminated 96 */ 97 HGCMFunctionParameter key; 98 99 /** 100 * The value of the key (OUT pointer) 99 * - Only Utf8 strings are allowed 100 * - Less than or equal to MAX_NAME_LEN bytes in length 101 * - Zero terminated 102 */ 103 HGCMFunctionParameter name; 104 105 /** 106 * The returned string data will be placed here. (OUT pointer) 107 * This call returns two null-terminated strings which will be placed one 108 * after another: value and flags. 109 */ 110 HGCMFunctionParameter buffer; 111 112 /** 113 * The property timestamp. (OUT uint64_t) 114 */ 115 116 HGCMFunctionParameter timestamp; 117 118 /** 119 * If the buffer provided was large enough this will contain the size of 120 * the returned data. Otherwise it will contain the size of the buffer 121 * needed to hold the data and VERR_BUFFER_OVERFLOW will be returned. 122 * (OUT uint32_t) 123 */ 124 HGCMFunctionParameter size; 125 } GetProperty; 126 127 /** The guest is requesting to change a property */ 128 typedef struct _SetProperty 129 { 130 VBoxGuestHGCMCallInfo hdr; 131 132 /** 133 * The property key. (IN pointer) 134 * This must fit to a number of criteria, namely 135 * - Only Utf8 strings are allowed 136 * - Less than or equal to MAX_NAME_LEN bytes in length 137 * - Zero terminated 138 */ 139 HGCMFunctionParameter name; 140 141 /** 142 * The value of the property (IN pointer) 143 * Criteria as for the key parameter, but with length less than or equal to 144 * MAX_VALUE_LEN. 101 145 */ 102 146 HGCMFunctionParameter value; 103 147 104 148 /** 105 * The size of the value. If this is greater than the size of the array106 * supplied in the second parameter then no data was transferred and the107 * call must be repeated. If it is zero then no value was found.108 * (OUT uint32_t)109 */ 110 HGCMFunctionParameter size;111 } GetConfigKey;112 113 /** The guest is requesting to change the value of a configuration key */114 typedef struct _Set ConfigKey115 { 116 VBoxGuestHGCMCallInfo hdr; 117 118 /** 119 * The key to change up. This must fit to a number of criteria, namely120 * - Only ASCII characters with no spaces121 * - Less than or equal to VBOX_SHARED_INFO_KEY_MAX_LEN bytes in length122 * - Zero terminated123 * /124 HGCMFunctionParameter key;125 126 /** 127 * The value of the key (IN pointer)128 * Criteria as for the key parameter, but with length less that or equal to129 * VBOX_SHARED_INFO_KEY_MAX_VALUE_LEN. A null pointer causes the valueto130 * be removed from the database.149 * The property flags (IN pointer) 150 * This is a comma-separated list of the format flag=value 151 * The length must be less than or equal to MAX_FLAGS_LEN and only 152 * known flag names and values will be accepted. 153 */ 154 HGCMFunctionParameter flags; 155 } SetProperty; 156 157 /** The guest is requesting to change the value of a property */ 158 typedef struct _SetPropertyValue 159 { 160 VBoxGuestHGCMCallInfo hdr; 161 162 /** 163 * The property key. (IN pointer) 164 * This must fit to a number of criteria, namely 165 * - Only Utf8 strings are allowed 166 * - Less than or equal to MAX_NAME_LEN bytes in length 167 * - Zero terminated 168 */ 169 HGCMFunctionParameter name; 170 171 /** 172 * The value of the property (IN pointer) 173 * Criteria as for the key parameter, but with length less than or equal to 174 * MAX_VALUE_LEN. 131 175 */ 132 176 HGCMFunctionParameter value; 133 } SetConfigKey; 134 135 /** The guest is requesting to remove a configuration key */ 136 typedef struct _DelConfigKey 137 { 138 VBoxGuestHGCMCallInfo hdr; 139 140 /** 141 * The key to change up. This must fit to a number of criteria, namely 142 * - Only ASCII characters with no spaces 143 * - Less than or equal to VBOX_SHARED_INFO_KEY_MAX_LEN bytes in length 144 * - Zero terminated 145 */ 146 HGCMFunctionParameter key; 147 } DelConfigKey; 177 } SetPropertyValue; 178 179 /** The guest is requesting to remove a property */ 180 typedef struct _DelProperty 181 { 182 VBoxGuestHGCMCallInfo hdr; 183 184 /** 185 * The property name. This must fit to a number of criteria, namely 186 * - Only Utf8 strings are allowed 187 * - Less than or equal to MAX_NAME_LEN bytes in length 188 * - Zero terminated 189 */ 190 HGCMFunctionParameter name; 191 } DelProperty; 192 193 /** The guest is requesting to enumerate properties */ 194 typedef struct _EnumProperties 195 { 196 VBoxGuestHGCMCallInfo hdr; 197 198 /** 199 * Null-separated array of patterns to match the properties against. 200 * (IN pointer) 201 * If no patterns are given then return all. 202 */ 203 HGCMFunctionParameter patterns; 204 /** 205 * Null-separated array of strings in which the properties are returned. 206 * (OUT pointer) 207 * The number of strings in the array is always a multiple of four, 208 * and in sequences of name, value, timestamp (hexadecimal string) and the 209 * flags as a comma-separated list in the format "name=value" 210 */ 211 HGCMFunctionParameter strings; 212 } EnumProperties; 148 213 #pragma pack () 149 214 150 } /* namespace svcInfo*/151 152 #endif /* ___VBox_HostService_ VBoxSharedInfoSvc_h defined */215 } /* namespace guestProp */ 216 217 #endif /* ___VBox_HostService_GuestPropertySvc_h defined */ trunk/include/VBox/VBoxGuest.h
r10651 r10797 1528 1528 /** @} */ 1529 1529 1530 #ifdef VBOX_WITH_ INFO_SVC1531 /** @name Information Services1530 #ifdef VBOX_WITH_GUEST_PROPS 1531 /** @name Guest properties 1532 1532 * @{ */ 1533 VBGLR3DECL(int) VbglR3InfoSvcConnect(uint32_t *pu32ClientId); 1534 VBGLR3DECL(int) VbglR3InfoSvcDisconnect(uint32_t u32ClientId); 1535 VBGLR3DECL(int) VbglR3InfoSvcWriteKey(uint32_t u32ClientId, char *pszKey, char *pszValue); 1536 VBGLR3DECL(int) VbglR3InfoSvcReadKey(uint32_t u32ClientId, char *pszKey, char *pszValue, uint32_t cbValue, uint32_t *pcbActual); 1533 VBGLR3DECL(int) VbglR3GuestPropConnect(uint32_t *pu32ClientId); 1534 VBGLR3DECL(int) VbglR3GuestPropDisconnect(uint32_t u32ClientId); 1535 VBGLR3DECL(int) VbglR3GuestPropWrite(uint32_t u32ClientId, char *pszName, char *pszValue, char *pszFlags); 1536 VBGLR3DECL(int) VbglR3GuestPropWriteValue(uint32_t u32ClientId, char *pszName, char *pszValue); 1537 VBGLR3DECL(int) VbglR3GuestPropRead(uint32_t u32ClientId, const char *pszName, void *pvBuf, uint32_t cbBuf, char **ppszValue, uint64_t *pu64Timestamp, char **ppszFlags, uint32_t *pcbBufActual); 1538 VBGLR3DECL(int) VbglR3GuestPropReadValue(uint32_t ClientId, const char *pszName, char *pszValue, uint32_t cchValue, uint32_t *pcchValueActual); 1539 VBGLR3DECL(int) VbglR3GuestPropReadValueAlloc(uint32_t u32ClientId, const char *pszName, char **ppszValue); 1540 VBGLR3DECL(void) VbglR3GuestPropReadValueFree(char *pszValue); 1537 1541 /** @} */ 1538 #endif /* VBOX_WITH_ INFO_SVCdefined */1542 #endif /* VBOX_WITH_GUEST_PROPS defined */ 1539 1543 1540 1544 trunk/src/VBox/Additions/WINNT/Makefile.kmk
r10129 r10797 34 34 include $(PATH_SUB_CURRENT)/VBoxTray/Makefile.kmk 35 35 include $(PATH_SUB_CURRENT)/VBoxGINA/Makefile.kmk 36 include $(PATH_SUB_CURRENT)/VBoxControl/Makefile.kmk37 36 include $(PATH_SUB_CURRENT)/VBoxHook/Makefile.kmk 38 37 ifndef VBOX_OSE trunk/src/VBox/Additions/common/Makefile.kmk
r10130 r10797 30 30 # Include sub-makefile. 31 31 include $(PATH_SUB_CURRENT)/VBoxGuestLib/Makefile.kmk 32 if1of ($(KBUILD_TARGET), freebsd linux os2 solaris)33 32 include $(PATH_SUB_CURRENT)/VBoxControl/Makefile.kmk 34 endif35 33 if1of ($(KBUILD_TARGET), freebsd os2 solaris) 36 34 include $(PATH_SUB_CURRENT)/VBoxGuest/Makefile.kmk trunk/src/VBox/Additions/common/VBoxControl/Makefile.kmk
r10127 r10797 33 33 PROGRAMS += VBoxControl 34 34 VBoxControl_TEMPLATE = VBOXGUESTR3EXE 35 ifdef VBOX_WITH_INFO_SVC 36 VBoxControl_DEFS += VBOX_HGCM VBOX_WITH_INFO_SVC 35 ifeq ($(KBUILD_TARGET),win) 36 ifdef VBOX_SIGN_ADDITIONS # (See the main Windows Additions makefile.) 37 VBoxControl_NOINST = true 38 endif 37 39 endif 40 VBoxControl_DEFS += \ 41 $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS VBOX_HGCM,) 38 42 VBoxControl_SOURCES = \ 39 43 VBoxControl.cpp \ 40 44 VBoxControlSVN.cpp 45 VBoxControl_SOURCES.win = \ 46 VBoxControl.rc 41 47 VBoxControl_LIBS = \ 42 48 $(VBOX_LIB_IPRT_GUEST_R3) \ trunk/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp
r10236 r10797 25 25 * Header Files * 26 26 *******************************************************************************/ 27 #include <iprt/ thread.h>27 #include <iprt/mem.h> 28 28 #include <iprt/string.h> 29 29 #include <iprt/stream.h> 30 30 #include <iprt/path.h> 31 31 #include <iprt/initterm.h> 32 #include <VBox/log.h> 32 33 #include <VBox/VBoxGuest.h> 33 34 #include <VBox/version.h> 34 #ifdef VBOX_WITH_INFO_SVC 35 # include <VBox/HostServices/VBoxInfoSvc.h> 35 #ifdef RT_OS_WINDOWS 36 # include <windows.h> 37 # include <malloc.h> /* for alloca */ 38 #endif 39 #ifdef VBOX_WITH_GUEST_PROPS 40 # include <VBox/HostServices/GuestPropertySvc.h> 36 41 #endif 37 42 #include "VBoxControl.h" … … 57 62 static void doUsage(char const *line, char const *name = "", char const *command = "") 58 63 { 59 RTPrintf("%s %-*s%s", name, 3 0- strlen(name), command, line);64 RTPrintf("%s %-*s%s", name, 32 - strlen(name), command, line); 60 65 } 61 66 … … 63 68 enum g_eUsage 64 69 { 65 #ifdef VBOX_WITH_INFO_SVC 70 #ifdef RT_OS_WINDOWS 71 GET_VIDEO_ACCEL, 72 SET_VIDEO_ACCEL, 73 LIST_CUST_MODES, 74 ADD_CUST_MODE, 75 REMOVE_CUST_MODE, 76 SET_VIDEO_MODE, 77 #endif 78 #ifdef VBOX_WITH_GUEST_PROPS 66 79 GET_GUEST_PROP, 67 80 SET_GUEST_PROP, … … 73 86 { 74 87 RTPrintf("Usage:\n\n"); 75 RTPrintf("%s [-v|--version] print version number and exit\n", g_pszProgName); 76 RTPrintf("%s --nologo ... suppress the logo\n\n", g_pszProgName); 77 78 #ifdef VBOX_WITH_INFO_SVC 88 RTPrintf("%s [-v|--version] print version number and exit\n", g_pszProgName); 89 RTPrintf("%s --nologo ... suppress the logo\n\n", g_pszProgName); 90 91 #ifdef RT_OS_WINDOWS 92 if ((GET_VIDEO_ACCEL == eWhich) || (USAGE_ALL == eWhich)) 93 doUsage("\n", g_pszProgName, "getvideoacceleration"); 94 if ((SET_VIDEO_ACCEL == eWhich) || (USAGE_ALL == eWhich)) 95 doUsage("<on|off>\n", g_pszProgName, "setvideoacceleration"); 96 if ((LIST_CUST_MODES == eWhich) || (USAGE_ALL == eWhich)) 97 doUsage("\n", g_pszProgName, "listcustommodes"); 98 if ((ADD_CUST_MODE == eWhich) || (USAGE_ALL == eWhich)) 99 doUsage("<width> <height> <bpp>\n", g_pszProgName, "addcustommode"); 100 if ((REMOVE_CUST_MODE == eWhich) || (USAGE_ALL == eWhich)) 101 doUsage("<width> <height> <bpp>\n", g_pszProgName, "removecustommode"); 102 if ((SET_VIDEO_MODE == eWhich) || (USAGE_ALL == eWhich)) 103 doUsage("<width> <height> <bpp> <screen>\n", g_pszProgName, "setvideomode"); 104 #endif 105 #ifdef VBOX_WITH_GUEST_PROPS 79 106 if ((GET_GUEST_PROP == eWhich) || (USAGE_ALL == eWhich)) 80 doUsage("< key>\n", g_pszProgName, "getguestproperty");107 doUsage("<name>\n", g_pszProgName, "getguestproperty"); 81 108 if ((SET_GUEST_PROP == eWhich) || (USAGE_ALL == eWhich)) 82 doUsage("< key> [<value>] (no value deletes key)\n", g_pszProgName, "setguestproperty");109 doUsage("<name> [<value>] (no value deletes property)\n", g_pszProgName, "setguestproperty"); 83 110 #endif 84 111 } … … 101 128 } 102 129 103 #ifdef VBOX_WITH_INFO_SVC 130 #ifdef RT_OS_WINDOWS 131 132 LONG (WINAPI * gpfnChangeDisplaySettingsEx)(LPCTSTR lpszDeviceName, LPDEVMODE lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam); 133 134 static unsigned nextAdjacentRectXP (RECTL *paRects, unsigned nRects, unsigned iRect) 135 { 136 unsigned i; 137 for (i = 0; i < nRects; i++) 138 { 139 if (paRects[iRect].right == paRects[i].left) 140 { 141 return i; 142 } 143 } 144 return ~0; 145 } 146 147 static unsigned nextAdjacentRectXN (RECTL *paRects, unsigned nRects, unsigned iRect) 148 { 149 unsigned i; 150 for (i = 0; i < nRects; i++) 151 { 152 if (paRects[iRect].left == paRects[i].right) 153 { 154 return i; 155 } 156 } 157 return ~0; 158 } 159 160 static unsigned nextAdjacentRectYP (RECTL *paRects, unsigned nRects, unsigned iRect) 161 { 162 unsigned i; 163 for (i = 0; i < nRects; i++) 164 { 165 if (paRects[iRect].bottom == paRects[i].top) 166 { 167 return i; 168 } 169 } 170 return ~0; 171 } 172 173 unsigned nextAdjacentRectYN (RECTL *paRects, unsigned nRects, unsigned iRect) 174 { 175 unsigned i; 176 for (i = 0; i < nRects; i++) 177 { 178 if (paRects[iRect].top == paRects[i].bottom) 179 { 180 return i; 181 } 182 } 183 return ~0; 184 } 185 186 void resizeRect(RECTL *paRects, unsigned nRects, unsigned iPrimary, unsigned iResized, int NewWidth, int NewHeight) 187 { 188 RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects); 189 memcpy (paNewRects, paRects, sizeof (RECTL) * nRects); 190 paNewRects[iResized].right += NewWidth - (paNewRects[iResized].right - paNewRects[iResized].left); 191 paNewRects[iResized].bottom += NewHeight - (paNewRects[iResized].bottom - paNewRects[iResized].top); 192 193 /* Verify all pairs of originally adjacent rectangles for all 4 directions. 194 * If the pair has a "good" delta (that is the first rectangle intersects the second) 195 * at a direction and the second rectangle is not primary one (which can not be moved), 196 * move the second rectangle to make it adjacent to the first one. 197 */ 198 199 /* X positive. */ 200 unsigned iRect; 201 for (iRect = 0; iRect < nRects; iRect++) 202 { 203 /* Find the next adjacent original rect in x positive direction. */ 204 unsigned iNextRect = nextAdjacentRectXP (paRects, nRects, iRect); 205 Log(("next %d -> %d\n", iRect, iNextRect)); 206 207 if (iNextRect == ~0 || iNextRect == iPrimary) 208 { 209 continue; 210 } 211 212 /* Check whether there is an X intesection between these adjacent rects in the new rectangles 213 * and fix the intersection if delta is "good". 214 */ 215 int delta = paNewRects[iRect].right - paNewRects[iNextRect].left; 216 217 if (delta > 0) 218 { 219 Log(("XP intersection right %d left %d, diff %d\n", 220 paNewRects[iRect].right, paNewRects[iNextRect].left, 221 delta)); 222 223 paNewRects[iNextRect].left += delta; 224 paNewRects[iNextRect].right += delta; 225 } 226 } 227 228 /* X negative. */ 229 for (iRect = 0; iRect < nRects; iRect++) 230 { 231 /* Find the next adjacent original rect in x negative direction. */ 232 unsigned iNextRect = nextAdjacentRectXN (paRects, nRects, iRect); 233 Log(("next %d -> %d\n", iRect, iNextRect)); 234 235 if (iNextRect == ~0 || iNextRect == iPrimary) 236 { 237 continue; 238 } 239 240 /* Check whether there is an X intesection between these adjacent rects in the new rectangles 241 * and fix the intersection if delta is "good". 242 */ 243 int delta = paNewRects[iRect].left - paNewRects[iNextRect].right; 244 245 if (delta < 0) 246 { 247 Log(("XN intersection left %d right %d, diff %d\n", 248 paNewRects[iRect].left, paNewRects[iNextRect].right, 249 delta)); 250 251 paNewRects[iNextRect].left += delta; 252 paNewRects[iNextRect].right += delta; 253 } 254 } 255 256 /* Y positive (in the computer sence, top->down). */ 257 for (iRect = 0; iRect < nRects; iRect++) 258 { 259 /* Find the next adjacent original rect in y positive direction. */ 260 unsigned iNextRect = nextAdjacentRectYP (paRects, nRects, iRect); 261 Log(("next %d -> %d\n", iRect, iNextRect)); 262 263 if (iNextRect == ~0 || iNextRect == iPrimary) 264 { 265 continue; 266 } 267 268 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles 269 * and fix the intersection if delta is "good". 270 */ 271 int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top; 272 273 if (delta > 0) 274 { 275 Log(("YP intersection bottom %d top %d, diff %d\n", 276 paNewRects[iRect].bottom, paNewRects[iNextRect].top, 277 delta)); 278 279 paNewRects[iNextRect].top += delta; 280 paNewRects[iNextRect].bottom += delta; 281 } 282 } 283 284 /* Y negative (in the computer sence, down->top). */ 285 for (iRect = 0; iRect < nRects; iRect++) 286 { 287 /* Find the next adjacent original rect in x negative direction. */ 288 unsigned iNextRect = nextAdjacentRectYN (paRects, nRects, iRect); 289 Log(("next %d -> %d\n", iRect, iNextRect)); 290 291 if (iNextRect == ~0 || iNextRect == iPrimary) 292 { 293 continue; 294 } 295 296 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles 297 * and fix the intersection if delta is "good". 298 */ 299 int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom; 300 301 if (delta < 0) 302 { 303 Log(("YN intersection top %d bottom %d, diff %d\n", 304 paNewRects[iRect].top, paNewRects[iNextRect].bottom, 305 delta)); 306 307 paNewRects[iNextRect].top += delta; 308 paNewRects[iNextRect].bottom += delta; 309 } 310 } 311 312 memcpy (paRects, paNewRects, sizeof (RECTL) * nRects); 313 return; 314 } 315 316 /* Returns TRUE to try again. */ 317 static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel) 318 { 319 BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0); 320 321 DISPLAY_DEVICE DisplayDevice; 322 323 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 324 DisplayDevice.cb = sizeof(DisplayDevice); 325 326 /* Find out how many display devices the system has */ 327 DWORD NumDevices = 0; 328 DWORD i = 0; 329 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 330 { 331 Log(("[%d] %s\n", i, DisplayDevice.DeviceName)); 332 333 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 334 { 335 Log(("Found primary device. err %d\n", GetLastError ())); 336 NumDevices++; 337 } 338 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 339 { 340 341 Log(("Found secondary device. err %d\n", GetLastError ())); 342 NumDevices++; 343 } 344 345 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 346 DisplayDevice.cb = sizeof(DisplayDevice); 347 i++; 348 } 349 350 Log(("Found total %d devices. err %d\n", NumDevices, GetLastError ())); 351 352 if (NumDevices == 0 || Id >= NumDevices) 353 { 354 Log(("Requested identifier %d is invalid. err %d\n", Id, GetLastError ())); 355 return FALSE; 356 } 357 358 DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices); 359 DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices); 360 RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices); 361 362 /* Fetch information about current devices and modes. */ 363 DWORD DevNum = 0; 364 DWORD DevPrimaryNum = 0; 365 366 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 367 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 368 369 i = 0; 370 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 371 { 372 Log(("[%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName)); 373 374 BOOL bFetchDevice = FALSE; 375 376 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 377 { 378 Log(("Found primary device. err %d\n", GetLastError ())); 379 DevPrimaryNum = DevNum; 380 bFetchDevice = TRUE; 381 } 382 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 383 { 384 385 Log(("Found secondary device. err %d\n", GetLastError ())); 386 bFetchDevice = TRUE; 387 } 388 389 if (bFetchDevice) 390 { 391 if (DevNum >= NumDevices) 392 { 393 Log(("%d >= %d\n", NumDevices, DevNum)); 394 return FALSE; 395 } 396 397 paDisplayDevices[DevNum] = DisplayDevice; 398 399 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE)); 400 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE); 401 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName, 402 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum])) 403 { 404 Log(("EnumDisplaySettings err %d\n", GetLastError ())); 405 return FALSE; 406 } 407 408 Log(("%dx%d at %d,%d\n", 409 paDeviceModes[DevNum].dmPelsWidth, 410 paDeviceModes[DevNum].dmPelsHeight, 411 paDeviceModes[DevNum].dmPosition.x, 412 paDeviceModes[DevNum].dmPosition.y)); 413 414 paRects[DevNum].left = paDeviceModes[DevNum].dmPosition.x; 415 paRects[DevNum].top = paDeviceModes[DevNum].dmPosition.y; 416 paRects[DevNum].right = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth; 417 paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight; 418 DevNum++; 419 } 420 421 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 422 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 423 i++; 424 } 425 426 if (Width == 0) 427 { 428 Width = paRects[Id].right - paRects[Id].left; 429 } 430 431 if (Height == 0) 432 { 433 Height = paRects[Id].bottom - paRects[Id].top; 434 } 435 436 /* Check whether a mode reset or a change is requested. */ 437 if ( !fModeReset 438 && paRects[Id].right - paRects[Id].left == Width 439 && paRects[Id].bottom - paRects[Id].top == Height 440 && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel) 441 { 442 Log(("VBoxDisplayThread : already at desired resolution.\n")); 443 return FALSE; 444 } 445 446 resizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height); 447 #ifdef Log 448 for (i = 0; i < NumDevices; i++) 449 { 450 Log(("[%d]: %d,%d %dx%d\n", 451 i, paRects[i].left, paRects[i].top, 452 paRects[i].right - paRects[i].left, 453 paRects[i].bottom - paRects[i].top)); 454 } 455 #endif /* Log */ 456 457 /* Without this, Windows will not ask the miniport for its 458 * mode table but uses an internal cache instead. 459 */ 460 DEVMODE tempDevMode; 461 ZeroMemory (&tempDevMode, sizeof (tempDevMode)); 462 tempDevMode.dmSize = sizeof(DEVMODE); 463 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode); 464 465 /* Assign the new rectangles to displays. */ 466 for (i = 0; i < NumDevices; i++) 467 { 468 paDeviceModes[i].dmPosition.x = paRects[i].left; 469 paDeviceModes[i].dmPosition.y = paRects[i].top; 470 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left; 471 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top; 472 473 paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH; 474 475 if ( i == Id 476 && BitsPerPixel != 0) 477 { 478 paDeviceModes[i].dmFields |= DM_BITSPERPEL; 479 paDeviceModes[i].dmBitsPerPel = BitsPerPixel; 480 } 481 Log(("calling pfnChangeDisplaySettingsEx %x\n", gpfnChangeDisplaySettingsEx)); 482 gpfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName, 483 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL); 484 Log(("ChangeDisplaySettings position err %d\n", GetLastError ())); 485 } 486 487 /* A second call to ChangeDisplaySettings updates the monitor. */ 488 LONG status = ChangeDisplaySettings(NULL, 0); 489 Log(("ChangeDisplaySettings update status %d\n", status)); 490 if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE) 491 { 492 /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */ 493 return FALSE; 494 } 495 496 /* Retry the request. */ 497 return TRUE; 498 } 499 500 int handleSetVideoMode(int argc, char *argv[]) 501 { 502 if (argc != 3 && argc != 4) 503 { 504 usage(SET_VIDEO_MODE); 505 return 1; 506 } 507 508 DWORD xres = atoi(argv[0]); 509 DWORD yres = atoi(argv[1]); 510 DWORD bpp = atoi(argv[2]); 511 DWORD scr = 0; 512 513 if (argc == 4) 514 { 515 scr = atoi(argv[3]); 516 } 517 518 HMODULE hUser = GetModuleHandle("USER32"); 519 520 if (hUser) 521 { 522 *(uintptr_t *)&gpfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA"); 523 Log(("VBoxService: pChangeDisplaySettingsEx = %p\n", gpfnChangeDisplaySettingsEx)); 524 525 if (gpfnChangeDisplaySettingsEx) 526 { 527 /* The screen index is 0 based in the ResizeDisplayDevice call. */ 528 scr = scr > 0? scr - 1: 0; 529 530 /* Horizontal resolution must be a multiple of 8, round down. */ 531 xres &= ~0x7; 532 533 ResizeDisplayDevice(scr, xres, yres, bpp); 534 } 535 } 536 return 0; 537 } 538 539 HKEY getVideoKey(bool writable) 540 { 541 HKEY hkeyDeviceMap = 0; 542 HKEY hkeyVideo = 0; 543 LONG status; 544 545 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkeyDeviceMap); 546 if ((status != ERROR_SUCCESS) || !hkeyDeviceMap) 547 { 548 VBoxControlError("Error opening video device map registry key!\n"); 549 return 0; 550 } 551 char szVideoLocation[256]; 552 DWORD dwKeyType; 553 szVideoLocation[0] = 0; 554 DWORD len = sizeof(szVideoLocation); 555 status = RegQueryValueExA(hkeyDeviceMap, "\\Device\\Video0", NULL, &dwKeyType, (LPBYTE)szVideoLocation, &len); 556 /* 557 * This value will start with a weird value: \REGISTRY\Machine 558 * Make sure this is true. 559 */ 560 if ( (status == ERROR_SUCCESS) 561 && (dwKeyType == REG_SZ) 562 && (_strnicmp(szVideoLocation, "\\REGISTRY\\Machine", 17) == 0)) 563 { 564 /* open that branch */ 565 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, &szVideoLocation[18], 0, KEY_READ | (writable ? KEY_WRITE : 0), &hkeyVideo); 566 } 567 else 568 { 569 VBoxControlError("Error opening registry key '%s'\n", &szVideoLocation[18]); 570 } 571 RegCloseKey(hkeyDeviceMap); 572 return hkeyVideo; 573 } 574 575 int handleGetVideoAcceleration(int argc, char *argv[]) 576 { 577 ULONG status; 578 HKEY hkeyVideo = getVideoKey(false); 579 580 if (hkeyVideo) 581 { 582 /* query the actual value */ 583 DWORD fAcceleration = 1; 584 DWORD len = sizeof(fAcceleration); 585 DWORD dwKeyType; 586 status = RegQueryValueExA(hkeyVideo, "EnableVideoAccel", NULL, &dwKeyType, (LPBYTE)&fAcceleration, &len); 587 if (status != ERROR_SUCCESS) 588 RTPrintf("Video acceleration: default\n"); 589 else 590 RTPrintf("Video acceleration: %s\n", fAcceleration ? "on" : "off"); 591 RegCloseKey(hkeyVideo); 592 } 593 return 0; 594 } 595 596 int handleSetVideoAcceleration(int argc, char *argv[]) 597 { 598 ULONG status; 599 HKEY hkeyVideo; 600 601 /* must have exactly one argument: the new offset */ 602 if ( (argc != 1) 603 || ( strcmp(argv[0], "on") 604 && strcmp(argv[0], "off"))) 605 { 606 usage(SET_VIDEO_ACCEL); 607 return 1; 608 } 609 610 hkeyVideo = getVideoKey(true); 611 612 if (hkeyVideo) 613 { 614 int fAccel = 0; 615 if (!strcmp(argv[0], "on")) 616 fAccel = 1; 617 /* set a new value */ 618 status = RegSetValueExA(hkeyVideo, "EnableVideoAccel", 0, REG_DWORD, (LPBYTE)&fAccel, sizeof(fAccel)); 619 if (status != ERROR_SUCCESS) 620 { 621 VBoxControlError("Error %d writing video acceleration status!\n", status); 622 } 623 RegCloseKey(hkeyVideo); 624 } 625 return 0; 626 } 627 628 #define MAX_CUSTOM_MODES 128 629 630 /* the table of custom modes */ 631 struct 632 { 633 DWORD xres; 634 DWORD yres; 635 DWORD bpp; 636 } customModes[MAX_CUSTOM_MODES] = {0}; 637 638 void getCustomModes(HKEY hkeyVideo) 639 { 640 ULONG status; 641 int curMode = 0; 642 643 /* null out the table */ 644 memset(customModes, 0, sizeof(customModes)); 645 646 do 647 { 648 char valueName[20]; 649 DWORD xres, yres, bpp = 0; 650 DWORD dwType; 651 DWORD dwLen = sizeof(DWORD); 652 653 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", curMode); 654 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&xres, &dwLen); 655 if (status != ERROR_SUCCESS) 656 break; 657 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", curMode); 658 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&yres, &dwLen); 659 if (status != ERROR_SUCCESS) 660 break; 661 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dBPP", curMode); 662 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&bpp, &dwLen); 663 if (status != ERROR_SUCCESS) 664 break; 665 666 /* check if the mode is OK */ 667 if ( (xres > (1 << 16)) 668 && (yres > (1 << 16)) 669 && ( (bpp != 16) 670 || (bpp != 24) 671 || (bpp != 32))) 672 break; 673 674 /* add mode to table */ 675 customModes[curMode].xres = xres; 676 customModes[curMode].yres = yres; 677 customModes[curMode].bpp = bpp; 678 679 ++curMode; 680 681 if (curMode >= MAX_CUSTOM_MODES) 682 break; 683 } while(1); 684 } 685 686 void writeCustomModes(HKEY hkeyVideo) 687 { 688 ULONG status; 689 int tableIndex = 0; 690 int modeIndex = 0; 691 692 /* first remove all values */ 693 for (int i = 0; i < MAX_CUSTOM_MODES; i++) 694 { 695 char valueName[20]; 696 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", i); 697 RegDeleteValueA(hkeyVideo, valueName); 698 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", i);

