VirtualBox

Changeset 70040 in vbox


Ignore:
Timestamp:
Dec 8, 2017 6:07:32 PM (7 years ago)
Author:
vboxsync
Message:

VBoxGuest: Sketched the code necessary to get configuration from the host via guest properties.

Location:
trunk/src/VBox/Additions/common/VBoxGuest
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp

    r69999 r70040  
    6161static NTSTATUS vgdrvNtDeviceControlSlow(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack);
    6262static NTSTATUS vgdrvNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
    63 static NTSTATUS vgdrvNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue);
     63static void     vgdrvNtReadConfiguration(PVBOXGUESTDEVEXTWIN pDevExt);
    6464static NTSTATUS vgdrvNtSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
    6565static NTSTATUS vgdrvNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp);
     
    535535    if (NT_SUCCESS(rcNt))
    536536    {
    537         ULONG uValue = 0x123;
    538         NTSTATUS rcNt2 = vgdrvNtRegistryReadDWORD(RTL_REGISTRY_SERVICES, L"VBoxGuest", L"LoggingEnabled", &uValue);
    539         if (NT_SUCCESS(rcNt2))
    540         {
    541             pDevExt->Core.fLoggingEnabled = uValue >= 0xFF;
    542             if (pDevExt->Core.fLoggingEnabled)
    543                 LogRelFunc(("Logging to host log enabled (%#x)", uValue));
    544         }
     537        /*
     538         * Once we've read configuration from register and host, we're finally read.
     539         */
     540        pDevExt->Core.fLoggingEnabled = true; /** @todo clean up guest ring-3 logging, keeping it separate from the kernel to avoid sharing limits with it. */
     541        vgdrvNtReadConfiguration(pDevExt);
    545542
    546543        /* Ready to rumble! */
     
    10981095 *                      registry value if found.
    10991096 */
    1100 static NTSTATUS vgdrvNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue)
     1097static NTSTATUS vgdrvNtRegistryReadDWORD(ULONG uRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue)
    11011098{
    11021099    if (!pwszPath || !pwszName || !puValue)
    11031100        return STATUS_INVALID_PARAMETER;
    11041101
    1105     ULONG ulDefault = *puValue;
    1106 
    1107     RTL_QUERY_REGISTRY_TABLE  tblQuery[2];
    1108     RtlZeroMemory(tblQuery, sizeof(tblQuery));
     1102    ULONG                       uDefault = *puValue;
     1103    RTL_QUERY_REGISTRY_TABLE    aQuery[2];
     1104    RT_ZERO(aQuery);
    11091105    /** @todo Add RTL_QUERY_REGISTRY_TYPECHECK! */
    1110     tblQuery[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
    1111     tblQuery[0].Name          = pwszName;
    1112     tblQuery[0].EntryContext  = puValue;
    1113     tblQuery[0].DefaultType   = REG_DWORD;
    1114     tblQuery[0].DefaultData   = &ulDefault;
    1115     tblQuery[0].DefaultLength = sizeof(ULONG);
    1116 
    1117     return RtlQueryRegistryValues(ulRoot,
    1118                                   pwszPath,
    1119                                   &tblQuery[0],
    1120                                   NULL /* Context */,
    1121                                   NULL /* Environment */);
     1106    aQuery[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
     1107    aQuery[0].Name          = pwszName;
     1108    aQuery[0].EntryContext  = puValue;
     1109    aQuery[0].DefaultType   = REG_DWORD;
     1110    aQuery[0].DefaultData   = &uDefault;
     1111    aQuery[0].DefaultLength = sizeof(uDefault);
     1112
     1113    return RtlQueryRegistryValues(uRoot, pwszPath, &aQuery[0], NULL /* Context */, NULL /* Environment */);
     1114}
     1115
     1116
     1117/**
     1118 * Reads configuration from the registry and guest properties.
     1119 *
     1120 * We ignore failures and instead preserve existing configuration values.
     1121 *
     1122 * Thie routine will block.
     1123 *
     1124 * @param   pDevExt             The device extension.
     1125 */
     1126static void vgdrvNtReadConfiguration(PVBOXGUESTDEVEXTWIN pDevExt)
     1127{
     1128    /*
     1129     * First the registry.
     1130     */
     1131    ULONG    uValue = 0;
     1132    NTSTATUS rcNt   = vgdrvNtRegistryReadDWORD(RTL_REGISTRY_SERVICES, L"VBoxGuest", L"LoggingEnabled", &uValue);
     1133    if (NT_SUCCESS(rcNt))
     1134    {
     1135        pDevExt->Core.fLoggingEnabled = uValue >= 0xFF;
     1136        if (pDevExt->Core.fLoggingEnabled)
     1137            LogRelFunc(("Logging to host log enabled (%#x)", uValue));
     1138    }
     1139
     1140#if 0 /* test me */
     1141    /*
     1142     * Read configuration from the host.
     1143     */
     1144    VGDrvCommonProcessOptionsFromHost(&pDevExt->Core);
     1145#endif
    11221146}
    11231147
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r69500 r70040  
    5555#include <VBox/VMMDev.h> /* for VMMDEV_RAM_SIZE */
    5656#include <VBox/log.h>
     57#include <iprt/ctype.h>
    5758#include <iprt/mem.h>
    5859#include <iprt/time.h>
     
    11351136}
    11361137
     1138#if 0 /* needs testing */
     1139
     1140#include <VBox/HostServices/GuestPropertySvc.h>
     1141
     1142/**
     1143 * Checks if the given option can be taken to no mean 'false'.
     1144 *
     1145 * @returns true or false accordingly.
     1146 * @param   pszValue            The value to consider.
     1147 */
     1148bool VBDrvCommonIsOptionValueTrue(const char *pszValue)
     1149{
     1150    if (pszValue)
     1151    {
     1152        char ch;
     1153        while (  (ch = *pszValue) != '\0'
     1154               && RT_C_IS_SPACE(ch))
     1155            pszValue++;
     1156
     1157        return ch != '\0'
     1158            && ch != 'n' /* no */
     1159            && ch != 'N' /* NO */
     1160            && ch != 'd' /* disabled */
     1161            && ch != 'D' /* DISABLED */
     1162            && (   (ch != 'o' && ch != 'O') /* off, OFF, Off */
     1163                || (pszValue[1] != 'f' && pszValue[1] != 'F') )
     1164            && (ch != '0' || pszValue[1] != '\0') /* '0' */
     1165            ;
     1166    }
     1167    return false;
     1168}
     1169
     1170
     1171/**
     1172 * Hook for handling OS specfic options from the host.
     1173 *
     1174 * @returns true if handled, false if not.
     1175 * @param   pDevExt         The device extension.
     1176 * @param   pszName         The option name.
     1177 * @param   pszValue        The option value.
     1178 */
     1179bool VGDrvNativeProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue)
     1180{
     1181    RT_NOREF(pDevExt); RT_NOREF(pszName); RT_NOREF(pszValue);
     1182    return false;
     1183}
     1184
     1185/**
     1186 * Processes a option.
     1187 *
     1188 * This will let the OS specific code have a go at it too.
     1189 *
     1190 * @param   pDevExt         The device extension.
     1191 * @param   pszName         The option name, sans prefix.
     1192 * @param   pszValue        The option value.
     1193 */
     1194void VGDrvCommonProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue)
     1195{
     1196    if (strcmp(pszName, "r3_log_to_host") == 0)
     1197        pDevExt->fLoggingEnabled = VBDrvCommonIsOptionValueTrue(pszValue);
     1198    else if (VGDrvNativeProcessOption(pDevExt, pszName, pszValue))
     1199        LogRel(("VBoxGuest: Ignoring unknown option '%s' (value '%s')\n", pszName, pszValue));
     1200}
     1201
     1202
     1203/**
     1204 * Read driver configuration from the host.
     1205 *
     1206 * This involves connecting to the guest properties service, which means that
     1207 * interrupts needs to work and that the calling thread must be able to block.
     1208 *
     1209 * @param   pDevExt     The device extension.
     1210 */
     1211void VGDrvCommonProcessOptionsFromHost(PVBOXGUESTDEVEXT pDevExt)
     1212{
     1213    /*
     1214     * Create a kernel session without our selves, then connect to the HGCM service.
     1215     */
     1216    PVBOXGUESTSESSION pSession;
     1217    int rc = VGDrvCommonCreateKernelSession(pDevExt, &pSession);
     1218    if (RT_SUCCESS(rc))
     1219    {
     1220        union
     1221        {
     1222            VBGLIOCHGCMCONNECT          Connect;
     1223            VBGLIOCHGCMDISCONNECT       Disconnect;
     1224            guestProp::EnumProperties   EnumMsg;
     1225        } uBuf;
     1226
     1227        RT_ZERO(uBuf.Connect);
     1228        VBGLREQHDR_INIT(&uBuf.Connect.Hdr, HGCM_CONNECT);
     1229        uBuf.Connect.u.In.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
     1230        RTStrCopy(uBuf.Connect.u.In.Loc.u.host.achName, sizeof(uBuf.Connect.u.In.Loc.u.host.achName),
     1231                  "VBoxGuestPropSvc"); /** @todo Add a define to the header for the name. */
     1232        rc = VGDrvCommonIoCtl(VBGL_IOCTL_HGCM_CONNECT, pDevExt, pSession, &uBuf.Connect.Hdr, sizeof(uBuf.Connect));
     1233        if (RT_SUCCESS(rc))
     1234        {
     1235            static const char   g_szzPattern[] = "/VirtualBox/GuestAdd/VBoxGuest/*\0";
     1236            uint32_t const      idClient       = uBuf.Connect.u.Out.idClient;
     1237            char               *pszzStrings    = NULL;
     1238            uint32_t            cbStrings;
     1239
     1240            /*
     1241             * Enumerate all the relevant properties.  We try with a 2KB buffer, but
     1242             * will double it until we get what we want or go beyond 64KB.
     1243             */
     1244            for (cbStrings = _2K; cbStrings <= _64K; cbStrings *= 2)
     1245            {
     1246                pszzStrings = (char *)RTMemAllocZ(cbStrings);
     1247                if (pszzStrings)
     1248                {
     1249                    VBGL_HGCM_HDR_INIT(&uBuf.EnumMsg.hdr, idClient, guestProp::ENUM_PROPS, 3);
     1250
     1251                    uBuf.EnumMsg.patterns.type                    = VMMDevHGCMParmType_LinAddr;
     1252                    uBuf.EnumMsg.patterns.u.Pointer.size          = sizeof(g_szzPattern);
     1253                    uBuf.EnumMsg.patterns.u.Pointer.u.linearAddr  = (uintptr_t)g_szzPattern;
     1254
     1255                    uBuf.EnumMsg.strings.type                     = VMMDevHGCMParmType_LinAddr;
     1256                    uBuf.EnumMsg.strings.u.Pointer.size           = cbStrings;
     1257                    uBuf.EnumMsg.strings.u.Pointer.u.linearAddr   = (uintptr_t)pszzStrings;
     1258
     1259                    uBuf.EnumMsg.size.type                        = VMMDevHGCMParmType_32bit;
     1260                    uBuf.EnumMsg.size.u.value32                   = 0;
     1261
     1262                    rc = VGDrvCommonIoCtl(VBGL_IOCTL_HGCM_CALL(sizeof(uBuf.EnumMsg)), pDevExt, pSession,
     1263                                          &uBuf.EnumMsg.hdr.Hdr, sizeof(uBuf.EnumMsg));
     1264                    if (RT_SUCCESS(rc))
     1265                        break;
     1266
     1267                    RTMemFree(pszzStrings);
     1268                    pszzStrings = NULL;
     1269                }
     1270                else
     1271                {
     1272                    LogRel(("VGDrvCommonReadConfigurationFromHost: failed to allocate %#x bytes\n", cbStrings));
     1273                    break;
     1274                }
     1275            }
     1276
     1277            /*
     1278             * Disconnect and destroy the session.
     1279             */
     1280            VBGLREQHDR_INIT(&uBuf.Disconnect.Hdr, HGCM_DISCONNECT);
     1281            uBuf.Disconnect.u.In.idClient = idClient;
     1282            VGDrvCommonIoCtl(VBGL_IOCTL_HGCM_DISCONNECT, pDevExt, pSession, &uBuf.Disconnect.Hdr, sizeof(uBuf.Disconnect));
     1283
     1284            VGDrvCommonCloseSession(pDevExt, pSession);
     1285
     1286            /*
     1287             * Process the properties if we got any.
     1288             *
     1289             * The string buffer contains packed strings in groups of four - name, value,
     1290             * timestamp (as a decimal string) and flags.  It is terminated by four empty
     1291             * strings.  Layout:
     1292             *   Name\0Value\0Timestamp\0Flags\0
     1293             */
     1294            if (pszzStrings)
     1295            {
     1296                uint32_t off;
     1297                for (off = 0; off < cbStrings; off++)
     1298                {
     1299                    /*
     1300                     * Parse the four fields, checking that it's all plain ASCII w/o any control characters.
     1301                     */
     1302                    const char *apszFields[4] = { NULL, NULL, NULL, NULL };
     1303                    bool        fValidFields  = true;
     1304                    unsigned    iField;
     1305                    for (iField = 0; iField < RT_ELEMENTS(apszFields); iField++)
     1306                    {
     1307                        apszFields[0] = &pszzStrings[off];
     1308                        while (off < cbStrings)
     1309                        {
     1310                            char ch = pszzStrings[off++];
     1311                            if ((unsigned)ch < 0x20U || (unsigned)ch > 0x7fU)
     1312                            {
     1313                                if (!ch)
     1314                                    break;
     1315                                fValidFields = false;
     1316                            }
     1317                        }
     1318                    }
     1319                    if (   off < cbStrings
     1320                        && fValidFields
     1321                        && *apszFields[0] != '\0')
     1322                    {
     1323                        /*
     1324                         * Validate and convert the flags to integer, then process the option.
     1325                         */
     1326                        uint32_t fFlags = 0;
     1327                        rc = guestProp::validateFlags(apszFields[3], &fFlags);
     1328                        if (RT_SUCCESS(rc))
     1329                        {
     1330                            if (fFlags & guestProp::RDONLYGUEST)
     1331                            {
     1332                                apszFields[0] += sizeof(g_szzPattern) - 2;
     1333                                VGDrvCommonProcessOption(pDevExt, apszFields[0], apszFields[1]);
     1334                            }
     1335                            else
     1336                                LogRel(("VBoxGuest: Ignoring '%s' as it does not have RDONLYGUEST set\n", apszFields[0]));
     1337                        }
     1338                        else
     1339                            LogRel(("VBoxGuest: Invalid flags '%s' for '%s': %Rrc\n", apszFields[2], apszFields[0], rc));
     1340                    }
     1341                    else if (off < cbStrings)
     1342                    {
     1343                        LogRel(("VBoxGuest: Malformed guest properties enum result!\n"));
     1344                        break;
     1345                    }
     1346                    else if (fValidFields)
     1347                        LogRel(("VBoxGuest: Ignoring %.*Rhxs as it has invalid characters in one or more fields\n",
     1348                                (int)strlen(apszFields[0]), apszFields[0]));
     1349                    else
     1350                        break;
     1351                }
     1352
     1353                RTMemFree(pszzStrings);
     1354            }
     1355            else
     1356                LogRel(("VGDrvCommonReadConfigurationFromHost: failed to enumerate '%s': %Rrc\n", g_szzPattern, rc));
     1357
     1358        }
     1359        else
     1360            LogRel(("VGDrvCommonReadConfigurationFromHost: failed to connect: %Rrc\n", rc));
     1361    }
     1362    else
     1363        LogRel(("VGDrvCommonReadConfigurationFromHost: failed to connect: %Rrc\n", rc));
     1364}
     1365
     1366#endif /* needs testing */
    11371367
    11381368/**
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r69500 r70040  
    325325int  VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, void *pvMMIOBase, uint32_t cbMMIO,
    326326                           VBOXOSTYPE enmOSType, uint32_t fEvents);
     327void VGDrvCommonProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue);
     328void VGDrvCommonProcessOptionsFromHost(PVBOXGUESTDEVEXT pDevExt);
    327329bool VGDrvCommonIsOurIRQ(PVBOXGUESTDEVEXT pDevExt);
    328330bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt);
     
    351353void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt);
    352354
     355/**
     356 * Hook for handling OS specfic options from the host.
     357 *
     358 * @returns true if handled, false if not.
     359 * @param   pDevExt         The device extension.
     360 * @param   pszName         The option name.
     361 * @param   pszValue        The option value.
     362 */
     363bool VGDrvNativeProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue);
     364
    353365
    354366#ifdef VBOX_WITH_DPC_LATENCY_CHECKER
Note: See TracChangeset for help on using the changeset viewer.

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