VirtualBox

Changeset 108285 in vbox


Ignore:
Timestamp:
Feb 19, 2025 10:53:35 AM (3 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167628
Message:

Host installer/win: Added routines for handling CustomActionData to the common InstallHelper.dll code. Required as a prerequisite for using shared (sessison / system) CustomActionData by the installer, to better support elevated driver installs on modern Windows OSes (>= 10). bugref:10762

Location:
trunk/src/VBox/Installer/win/InstallHelper
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp

    r108071 r108285  
    3636#include <msiquery.h>
    3737
     38#include <iprt/mem.h>
    3839#include <iprt/string.h>
    3940#include <iprt/utf16.h>
     
    9495}
    9596#endif /* !TESTCASE */
     97
     98/**
     99 * Destroys a custom action data entry.
     100 *
     101 * @param   pEntry              Custom action data entry to destroy.
     102 */
     103static void vboxMsiCustomActionDataEntryDestroy(PVBOXMSICUSTOMACTIONDATAENTRY pEntry)
     104{
     105    if (!pEntry)
     106        return;
     107
     108    RTStrFree(pEntry->pszKey);
     109    pEntry->pszKey = NULL;
     110    RTStrFree(pEntry->pszVal);
     111    pEntry->pszVal = NULL;
     112}
     113
     114/**
     115 * Queries custom action data entries, extended version.
     116 *
     117 * @returns VBox status code.
     118 * @param   hMsi                MSI handle to use.
     119 * @param   pszSep              Separator to use for parsing the key=value pairs.
     120 * @param   ppaEntries          Where to return the allocated custom action data entries.
     121                                Might be NULL if \a pcEntries returns 0.
     122 *                              Must be destroyed using vboxMsiCustomActionDataEntryDestroy().
     123 * @param   pcEntries           Where to return the number of allocated custom action data entries of \a ppaEntries.
     124 *
     125 * @note    The "CustomActionData" property used is fixed by the MSI engine and must not be changed.
     126 */
     127static int vboxMsiCustomActionDataQueryEx(MSIHANDLE hMsi, const char *pszSep, PVBOXMSICUSTOMACTIONDATAENTRY *ppaEntries, size_t *pcEntries)
     128{
     129    char *pszData = NULL;
     130    int rc = VBoxMsiQueryPropUtf8(hMsi, "CustomActionData", &pszData);
     131    if (RT_FAILURE(rc))
     132        return rc;
     133
     134    *ppaEntries = NULL;
     135
     136    char **ppapszPairs; /* key=value pairs. */
     137    size_t cPairs;
     138    rc = RTStrSplit(pszData, strlen(pszData) + 1 /* Must include terminator */, pszSep, &ppapszPairs, &cPairs);
     139    if (   RT_SUCCESS(rc)
     140        && cPairs)
     141    {
     142        PVBOXMSICUSTOMACTIONDATAENTRY paEntries =
     143            (PVBOXMSICUSTOMACTIONDATAENTRY)RTMemAllocZ(cPairs * sizeof(VBOXMSICUSTOMACTIONDATAENTRY));
     144        if (paEntries)
     145        {
     146            size_t i = 0;
     147            for (; i < cPairs; i++)
     148            {
     149                const char *pszPair = ppapszPairs[i];
     150
     151                char **ppapszKeyVal;
     152                size_t cKeyVal;
     153                rc = RTStrSplit(pszPair, strlen(pszPair) + 1 /* Must include terminator */, "=", &ppapszKeyVal, &cKeyVal);
     154                if (RT_SUCCESS(rc))
     155                {
     156                    if (cKeyVal == 2) /* Exactly one key=val pair. */
     157                    {
     158                        /* paEntries[i] will take ownership of ppapszKeyVal. */
     159                        paEntries[i].pszKey = ppapszKeyVal[0];
     160                        ppapszKeyVal[0] = NULL;
     161                        paEntries[i].pszVal = ppapszKeyVal[1];
     162                        ppapszKeyVal[1] = NULL;
     163                    }
     164                    else
     165                        rc = VERR_INVALID_PARAMETER;
     166
     167                    for (size_t a = 0; a < cKeyVal; a++)
     168                        RTStrFree(ppapszKeyVal[a]);
     169                    RTMemFree(ppapszKeyVal);
     170                }
     171
     172                if (RT_FAILURE(rc))
     173                    break;
     174            }
     175
     176            if (RT_FAILURE(rc))
     177            {
     178                /* Rollback on failure. */
     179                while (i)
     180                    vboxMsiCustomActionDataEntryDestroy(&paEntries[i--]);
     181                RTMemFree(paEntries);
     182            }
     183            else
     184            {
     185                *ppaEntries = paEntries;
     186                *pcEntries  = cPairs;
     187            }
     188        }
     189        else
     190            rc = VERR_NO_MEMORY;
     191
     192        for (size_t i = 0; i < cPairs; i++)
     193            RTStrFree(ppapszPairs[i]);
     194        RTMemFree(ppapszPairs);
     195    }
     196
     197    return rc;
     198}
     199
     200/**
     201 * Queries custom action data entries.
     202 *
     203 * @returns VBox status code.
     204 * @param   hMsi                MSI handle to use.
     205 * @param   ppaEntries          Where to return the allocated custom action data entries.
     206 *                              Must be destroyed using vboxMsiCustomActionDataEntryDestroy().
     207 * @param   pcEntries           Where to return the number of allocated custom action data entries of \a ppaEntries.
     208 */
     209static int vboxMsiCustomActionDataQuery(MSIHANDLE hMsi, PVBOXMSICUSTOMACTIONDATAENTRY *ppaEntries, size_t *pcEntries)
     210{
     211    return vboxMsiCustomActionDataQueryEx(hMsi, VBOX_MSI_CUSTOMACTIONDATA_SEP_STR, ppaEntries, pcEntries);
     212}
     213
     214/**
     215 * Frees custom action data.
     216 *
     217 * @returns VBox status code.
     218 * @param   pData               Custom action data to free.
     219 *                              The pointer will be invalid on return.
     220 */
     221void VBoxMsiCustomActionDataFree(PVBOXMSICUSTOMACTIONDATA pData)
     222{
     223    if (!pData)
     224        return;
     225
     226    for (size_t i = 0; i < pData->cEntries; i++)
     227        vboxMsiCustomActionDataEntryDestroy(&pData->paEntries[i]);
     228
     229    RTMemFree(pData);
     230    pData = NULL;
     231}
     232
     233/**
     234 * Queries custom action data, extended version.
     235 *
     236 * @returns VBox status code.
     237 * @param   hMsi                MSI handle to use.
     238 * @param   pszSep              Separator to use for parsing the key=value pairs.
     239 * @param   ppData              Where to return the allocated custom action data.
     240 *                              Needs to be free'd using VBoxMsiCustomActionDataFree().
     241 */
     242int VBoxMsiCustomActionDataQueryEx(MSIHANDLE hMsi, const char *pszSep, PVBOXMSICUSTOMACTIONDATA *ppData)
     243{
     244    AssertPtrReturn(pszSep, VERR_INVALID_POINTER);
     245    AssertPtrReturn(ppData, VERR_INVALID_POINTER);
     246
     247    PVBOXMSICUSTOMACTIONDATA pData = (PVBOXMSICUSTOMACTIONDATA)RTMemAllocZ(sizeof(VBOXMSICUSTOMACTIONDATA));
     248    AssertPtrReturn(pData, VERR_NO_MEMORY);
     249
     250    int rc = vboxMsiCustomActionDataQueryEx(hMsi, pszSep, &pData->paEntries, &pData->cEntries);
     251    if (RT_SUCCESS(rc))
     252    {
     253        *ppData = pData;
     254    }
     255    else
     256        VBoxMsiCustomActionDataFree(pData);
     257
     258    return rc;
     259}
     260
     261/**
     262 * Queries custom action data.
     263 *
     264 * @returns VBox status code.
     265 * @param   hMsi                MSI handle to use.
     266 * @param   ppData              Where to return the allocated custom action data.
     267 *                              Needs to be free'd using VBoxMsiCustomActionDataFree().
     268 */
     269int VBoxMsiCustomActionDataQuery(MSIHANDLE hMsi, PVBOXMSICUSTOMACTIONDATA *ppData)
     270{
     271    return VBoxMsiCustomActionDataQueryEx(hMsi, VBOX_MSI_CUSTOMACTIONDATA_SEP_STR, ppData);
     272}
     273
     274/**
     275 * Finds a key in custom action data and returns its value.
     276 *
     277 * @returns Value if found, or NULL if not found.
     278 * @param   pHaystack           Custom action data to search in.
     279 * @param   pszNeedle           Key to search for. Case-sensitive.
     280 */
     281const char *VBoxMsiCustomActionDataFind(PVBOXMSICUSTOMACTIONDATA pHaystack, const char *pszNeedle)
     282{
     283    AssertPtrReturn(pHaystack, NULL);
     284    AssertPtrReturn(pszNeedle, NULL);
     285
     286    for (size_t i = 0; i < pHaystack->cEntries; i++)
     287    {
     288        if (!RTStrICmp(pHaystack->paEntries[i].pszKey, pszNeedle))
     289            return pHaystack->paEntries[i].pszVal;
     290    }
     291
     292    return NULL;
     293}
    96294
    97295/**
  • trunk/src/VBox/Installer/win/InstallHelper/VBoxCommon.h

    r108071 r108285  
    3636#endif
    3737
     38/** Struct for keeping a single "CustomActionData" key=value item. */
     39typedef struct VBOXMSICUSTOMACTIONDATAENTRY
     40{
     41    /** Key (name) of the item. */
     42    char *pszKey;
     43    /** Value of the item. Always a string but can represent other stuff. Use with care. */
     44    char *pszVal;
     45} VBOXMSICUSTOMACTIONDATAENTRY;
     46/** Pointer to a struct for keeping a single "CustomActionData" key=value item. */
     47typedef VBOXMSICUSTOMACTIONDATAENTRY *PVBOXMSICUSTOMACTIONDATAENTRY;
     48
     49/** Struct for keeping "CustomActionData" entries. */
     50typedef struct VBOXMSICUSTOMACTIONDATA
     51{
     52    /** Array of CustomActionData entries. */
     53    PVBOXMSICUSTOMACTIONDATAENTRY paEntries;
     54    /** Number of entries in \a paEntries. */
     55    size_t                        cEntries;
     56} VBOXMSICUSTOMACTIONDATA;
     57/** Pointer to a struct for keeping "CustomActionData" entries. */
     58typedef VBOXMSICUSTOMACTIONDATA *PVBOXMSICUSTOMACTIONDATA;
     59
     60/** Default separator for custom action data key=value pairs. */
     61#define VBOX_MSI_CUSTOMACTIONDATA_SEP_STR "##"
     62
     63void VBoxMsiCustomActionDataFree(PVBOXMSICUSTOMACTIONDATA pData);
     64int  VBoxMsiCustomActionDataQueryEx(MSIHANDLE hMsi, const char *pszSep, PVBOXMSICUSTOMACTIONDATA *ppData);
     65int  VBoxMsiCustomActionDataQuery(MSIHANDLE hMsi, PVBOXMSICUSTOMACTIONDATA *ppData);
     66const char *VBoxMsiCustomActionDataFind(PVBOXMSICUSTOMACTIONDATA pHaystack, const char *pszNeedle);
     67
    3868int  VBoxMsiQueryProp(MSIHANDLE hMsi, const WCHAR *pwszName, WCHAR *pwszVal, DWORD cwVal);
    3969int  VBoxMsiQueryPropEx(MSIHANDLE hMsi, const WCHAR *pwszName, WCHAR *pwszVal, DWORD *pcwVal);
     
    4171int  VBoxMsiQueryPropInt32(MSIHANDLE hMsi, const char *pszName, DWORD *pdwValue);
    4272UINT VBoxMsiSetProp(MSIHANDLE hMsi, const WCHAR *pwszName, const WCHAR *pwszValue);
    43 int VBoxMsiSetPropUtf8(MSIHANDLE hMsi, const char *pszName, const char *pszValue);
     73int  VBoxMsiSetPropUtf8(MSIHANDLE hMsi, const char *pszName, const char *pszValue);
    4474UINT VBoxMsiSetPropDWORD(MSIHANDLE hMsi, const WCHAR *pwszName, DWORD dwVal);
    45 int VBoxMsiRegQueryDWORDW(MSIHANDLE hMsi, HKEY hKey, LPCWSTR pwszName, DWORD *pdwValue);
    46 int VBoxMsiRegQueryDWORD(MSIHANDLE hMsi, HKEY hKey, const char *pszName, DWORD *pdwValue);
     75int  VBoxMsiRegQueryDWORDW(MSIHANDLE hMsi, HKEY hKey, LPCWSTR pwszName, DWORD *pdwValue);
     76int  VBoxMsiRegQueryDWORD(MSIHANDLE hMsi, HKEY hKey, const char *pszName, DWORD *pdwValue);
    4777
    4878#endif /* !VBOX_INCLUDED_SRC_InstallHelper_VBoxCommon_h */
Note: See TracChangeset for help on using the changeset viewer.

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