VirtualBox

Changeset 96390 in vbox


Ignore:
Timestamp:
Aug 21, 2022 2:04:19 AM (2 years ago)
Author:
vboxsync
Message:

Add/NT/Inst: Cleaned up VBoxGuestDrvInst so it compiles cleanly in no-CRT mode. Ditched the UNICODE / tchar fun in favor adding missing 'W's. Switch the build config to always build x86 version, since this is another NT4 helper. bugref:10261

Location:
trunk/src/VBox/Additions/WINNT/Installer
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk

    r96387 r96390  
    4747
    4848PROGRAMS += VBoxGuestDrvInst
    49 VBoxGuestDrvInst_TEMPLATE= VBoxGuestR3Exe
    50 VBoxGuestDrvInst_DEFS    =  _WIN32_WINNT=0x0400 UNICODE
    51 VBoxGuestDrvInst_SOURCES = \
     49VBoxGuestDrvInst_TEMPLATE     := VBoxGuestR3Exe
     50VBoxGuestDrvInst_DEFS         :=  _WIN32_WINNT=0x0400
     51VBoxGuestDrvInst_BLD_TRG_ARCH := x86
     52VBoxGuestDrvInst_SOURCES      := \
    5253        VBoxGuestDrvInst.cpp \
    5354        VBoxGuestDrvInst.rc
  • trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.cpp

    r93115 r96390  
    1616 */
    1717
    18 /**
    19  * @todo
    20  * The spacing in this file is horrible! Here are some simple rules:
    21  * - tabs are forbidden
    22  * - indentation is 4 spaces
    23  */
    24 
    25 
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    2622#include <iprt/win/windows.h>
    2723#include <iprt/win/setupapi.h>
    2824#include <regstr.h>
    2925#include <DEVGUID.h>
    30 #include <stdio.h>
    31 
    32 #include "tchar.h"
    33 #include "string.h"
     26
     27#include <iprt/path.h>
     28#include <iprt/string.h>
     29#include <iprt/utf16.h>
     30
    3431
    3532
     
    3734*   Defined Constants And Macros                                                                                                 *
    3835*********************************************************************************************************************************/
    39 
    4036/** The video service name. */
    41 #define  VBOXGUEST_VIDEO_NAME    "VBoxVideo"
     37#define VBOXGUEST_VIDEO_NAME        "VBoxVideo"
    4238
    4339/** The video inf file name */
    44 #define  VBOXGUEST_VIDEO_INF_NAME    "VBoxVideo.inf"
    45 
    46 /////////////////////////////////////////////////////////////////////////////
     40#define VBOXGUEST_VIDEO_INF_NAME    "VBoxVideo.inf"
     41
     42
     43/*
     44 * A few error messaging functions that avoids dragging in printf-like stuff.
     45 */
     46
     47static RTEXITCODE ErrorMsg(const char *pszMsg)
     48{
     49    HANDLE const hStdOut = GetStdHandle(STD_ERROR_HANDLE);
     50    DWORD        cbIgn;
     51    WriteFile(hStdOut, RT_STR_TUPLE("error: "), &cbIgn, NULL);
     52    WriteFile(hStdOut, pszMsg, (DWORD)strlen(pszMsg), &cbIgn, NULL);
     53    WriteFile(hStdOut, RT_STR_TUPLE("\r\n"), &cbIgn, NULL);
     54    return RTEXITCODE_FAILURE;
     55}
     56
     57
     58static RTEXITCODE ErrorMsgErr(const char *pszMsg, DWORD dwErr, const char *pszErrIntro, size_t cchErrIntro, bool fSigned)
     59{
     60    HANDLE const hStdOut = GetStdHandle(STD_ERROR_HANDLE);
     61    DWORD        cbIgn;
     62    WriteFile(hStdOut, RT_STR_TUPLE("error: "), &cbIgn, NULL);
     63    WriteFile(hStdOut, pszMsg, (DWORD)strlen(pszMsg), &cbIgn, NULL);
     64    WriteFile(hStdOut, pszErrIntro, (DWORD)cchErrIntro, &cbIgn, NULL);
     65    char    szVal[128];
     66    ssize_t cchVal = RTStrFormatU32(szVal, sizeof(szVal), dwErr, 10, 0, 0, fSigned ? RTSTR_F_VALSIGNED : 0);
     67    WriteFile(hStdOut, szVal, (DWORD)cchVal, &cbIgn, NULL);
     68    WriteFile(hStdOut, RT_STR_TUPLE("/\r\n"), &cbIgn, NULL);
     69    cchVal = RTStrFormatU32(szVal, sizeof(szVal), dwErr, 16, 0, 0, RTSTR_F_SPECIAL);
     70    WriteFile(hStdOut, szVal, (DWORD)cchVal, &cbIgn, NULL);
     71    WriteFile(hStdOut, RT_STR_TUPLE(")\r\n"), &cbIgn, NULL);
     72    return RTEXITCODE_FAILURE;
     73}
     74
     75
     76static RTEXITCODE ErrorMsgLastErr(const char *pszMsg)
     77{
     78    return ErrorMsgErr(pszMsg, GetLastError(), RT_STR_TUPLE(" (last error "), false);
     79}
     80
     81
     82static RTEXITCODE ErrorMsgLStatus(const char *pszMsg, LSTATUS lrc)
     83{
     84    return ErrorMsgErr(pszMsg, (DWORD)lrc, RT_STR_TUPLE(" ("), true);
     85}
    4786
    4887
    4988
    5089/**
    51  * Do some cleanup of data we used. Called by installVideoDriver()
     90 * Inner video driver installation function.
     91 *
     92 * This can normally return immediately on errors as the parent will do the
     93 * cleaning up.
    5294 */
    53 void closeAndDestroy(HDEVINFO hDevInfo, HINF hInf)
    54 {
    55   SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
    56   SetupDiDestroyDeviceInfoList(hDevInfo);
    57   SetupCloseInfFile(hInf);
    58 }
     95static RTEXITCODE InstallVideoDriverInner(WCHAR const * const pwszDriverDir, HDEVINFO hDevInfo, HINF *phInf)
     96{
     97    /*
     98     * Get the first found driver.
     99     * Our Inf file only contains one so this is fine.
     100     */
     101    SP_DRVINFO_DATA_W drvInfoData = { sizeof(SP_DRVINFO_DATA) };
     102    if (!SetupDiEnumDriverInfoW(hDevInfo, NULL, SPDIT_CLASSDRIVER, 0, &drvInfoData))
     103        return ErrorMsgLastErr("SetupDiEnumDriverInfoW");
     104
     105    /*
     106     * Get necessary driver details
     107     */
     108    union
     109    {
     110        SP_DRVINFO_DETAIL_DATA_W s;
     111        uint64_t                 au64Padding[(sizeof(SP_DRVINFO_DETAIL_DATA_W) + 256) / sizeof(uint64_t)];
     112    } DriverInfoDetailData = { { sizeof(SP_DRVINFO_DETAIL_DATA) } };
     113    DWORD                    cbReqSize            = NULL;
     114    if (   !SetupDiGetDriverInfoDetailW(hDevInfo, NULL, &drvInfoData,
     115                                        &DriverInfoDetailData.s, sizeof(DriverInfoDetailData), &cbReqSize)
     116        && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
     117        return ErrorMsgLastErr("SetupDiGetDriverInfoDetailW");
     118
     119    HINF hInf = *phInf = SetupOpenInfFileW(DriverInfoDetailData.s.InfFileName, NULL, INF_STYLE_WIN4, NULL);
     120    if (hInf == INVALID_HANDLE_VALUE)
     121        return ErrorMsgLastErr("SetupOpenInfFileW");
     122
     123    /*
     124     * First install the service.
     125     */
     126    WCHAR wszServiceSection[LINE_LEN];
     127    int rc = RTUtf16Copy(wszServiceSection, RT_ELEMENTS(wszServiceSection), DriverInfoDetailData.s.SectionName);
     128    if (RT_SUCCESS(rc))
     129        rc = RTUtf16CatAscii(wszServiceSection, RT_ELEMENTS(wszServiceSection), ".Services");
     130    if (RT_FAILURE(rc))
     131        return ErrorMsg("wszServiceSection too small");
     132
     133    INFCONTEXT SvcCtx;
     134    if (!SetupFindFirstLineW(hInf, wszServiceSection, NULL, &SvcCtx))
     135        return ErrorMsgLastErr("SetupFindFirstLine"); /* impossible... */
     136
     137    /*
     138     * Get the name
     139     */
     140    WCHAR wszServiceData[LINE_LEN] = {0};
     141    if (!SetupGetStringFieldW(&SvcCtx, 1, wszServiceData, RT_ELEMENTS(wszServiceData), NULL))
     142        return ErrorMsgLastErr("SetupGetStringFieldW");
     143
     144    WCHAR wszDevInstanceId[LINE_LEN];
     145    rc = RTUtf16CopyAscii(wszDevInstanceId, RT_ELEMENTS(wszDevInstanceId), "Root\\LEGACY_");
     146    if (RT_SUCCESS(rc))
     147        rc = RTUtf16Cat(wszDevInstanceId, RT_ELEMENTS(wszDevInstanceId), wszServiceData);
     148    if (RT_SUCCESS(rc))
     149        rc = RTUtf16CatAscii(wszDevInstanceId, RT_ELEMENTS(wszDevInstanceId), "\\0000");
     150    if (RT_FAILURE(rc))
     151        return ErrorMsg("wszDevInstanceId too small");
     152
     153    /*
     154     * ...
     155     */
     156    SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) };
     157    /* Check for existing first. */
     158    BOOL fDevInfoOkay = SetupDiOpenDeviceInfoW(hDevInfo, wszDevInstanceId, NULL, 0, &deviceInfoData);
     159    if (!fDevInfoOkay)
     160    {
     161        /* Okay, try create a new device info element. */
     162        if (SetupDiCreateDeviceInfoW(hDevInfo, wszDevInstanceId, (LPGUID)&GUID_DEVCLASS_DISPLAY,
     163                                     NULL, // Do we need a description here?
     164                                     NULL, // No user interface
     165                                     0, &deviceInfoData))
     166        {
     167            if (SetupDiRegisterDeviceInfo(hDevInfo, &deviceInfoData, 0, NULL, NULL, NULL))
     168                fDevInfoOkay = TRUE;
     169            else
     170                return ErrorMsgLastErr("SetupDiRegisterDeviceInfo"); /** @todo Original code didn't return here. */
     171        }
     172        else
     173            return ErrorMsgLastErr("SetupDiCreateDeviceInfoW"); /** @todo Original code didn't return here. */
     174    }
     175    if (fDevInfoOkay) /** @todo if not needed if it's okay to fail on failure above */
     176    {
     177        /* We created a new key in the registry */ /* bogus... */
     178
     179        /*
     180         * Redo the install parameter thing with deviceInfoData.
     181         */
     182        SP_DEVINSTALL_PARAMS_W DeviceInstallParams = { sizeof(SP_DEVINSTALL_PARAMS) };
     183        if (!SetupDiGetDeviceInstallParamsW(hDevInfo, &deviceInfoData, &DeviceInstallParams))
     184            return ErrorMsgLastErr("SetupDiGetDeviceInstallParamsW(#2)"); /** @todo Original code didn't return here. */
     185
     186        DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
     187        DeviceInstallParams.Flags |= DI_NOFILECOPY      /* We did our own file copying */
     188                                   | DI_DONOTCALLCONFIGMG
     189                                   | DI_ENUMSINGLEINF;  /* .DriverPath specifies an inf file */
     190        rc = RTUtf16Copy(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath), pwszDriverDir);
     191        if (RT_SUCCESS(rc))
     192            rc = RTUtf16CatAscii(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath),
     193                                 VBOXGUEST_VIDEO_INF_NAME);
     194        if (RT_FAILURE(rc))
     195            return ErrorMsg("Install dir too deep (long)");
     196
     197        if (!SetupDiSetDeviceInstallParamsW(hDevInfo, &deviceInfoData, &DeviceInstallParams))
     198            return ErrorMsgLastErr("SetupDiSetDeviceInstallParamsW(#2)"); /** @todo Original code didn't return here. */
     199
     200        if (!SetupDiBuildDriverInfoList(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER))
     201            return ErrorMsgLastErr("SetupDiBuildDriverInfoList(#2)");
     202
     203        /*
     204         * Repeate the query at the start of the function.
     205         */
     206        drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
     207        if (!SetupDiEnumDriverInfoW(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER, 0, &drvInfoData))
     208            return ErrorMsgLastErr("SetupDiEnumDriverInfoW(#2)");
     209
     210        /*
     211         * ...
     212         */
     213        if (!SetupDiSetSelectedDriverW(hDevInfo, &deviceInfoData, &drvInfoData))
     214            return ErrorMsgLastErr("SetupDiSetSelectedDriverW(#2)");
     215
     216        if (!SetupDiInstallDevice(hDevInfo, &deviceInfoData))
     217            return ErrorMsgLastErr("SetupDiInstallDevice(#2)");
     218    }
     219
     220    /*
     221     * Make sure the device is enabled.
     222     */
     223    DWORD fConfig = 0;
     224    if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS,
     225                                          NULL, (LPBYTE)&fConfig, sizeof(DWORD), NULL))
     226    {
     227        if (fConfig & CONFIGFLAG_DISABLED)
     228        {
     229            fConfig &= ~CONFIGFLAG_DISABLED;
     230            if (!SetupDiSetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS,
     231                                                   (LPBYTE)&fConfig, sizeof(fConfig)))
     232                ErrorMsg("SetupDiSetDeviceRegistryPropertyW");
     233        }
     234    }
     235    else
     236        ErrorMsg("SetupDiGetDeviceRegistryPropertyW");
     237
     238    /*
     239     * Open the service key.
     240     */
     241    WCHAR wszSvcRegKey[LINE_LEN + 64];
     242    rc = RTUtf16CopyAscii(wszSvcRegKey, RT_ELEMENTS(wszSvcRegKey), "System\\CurrentControlSet\\Services\\");
     243    if (RT_SUCCESS(rc))
     244        rc = RTUtf16Cat(wszSvcRegKey, RT_ELEMENTS(wszSvcRegKey), wszServiceData);
     245    if (RT_SUCCESS(rc))
     246        rc = RTUtf16CatAscii(wszSvcRegKey, RT_ELEMENTS(wszSvcRegKey), "\\Device0"); /* We only have one device. */
     247    if (RT_FAILURE(rc))
     248        return ErrorMsg("Service key name too long");
     249
     250    DWORD   dwIgn;
     251    HKEY    hKey = NULL;
     252    LSTATUS lrc  = RegCreateKeyExW(HKEY_LOCAL_MACHINE, wszSvcRegKey, 0, NULL, REG_OPTION_NON_VOLATILE,
     253                                   KEY_READ | KEY_WRITE, NULL, &hKey, &dwIgn);
     254    if (lrc == ERROR_SUCCESS)
     255    {
     256        /*
     257         * Insert service description.
     258         */
     259        lrc = RegSetValueExW(hKey, L"Device Description", 0, REG_SZ, (LPBYTE)DriverInfoDetailData.s.DrvDescription,
     260                            (DWORD)((RTUtf16Len(DriverInfoDetailData.s.DrvDescription) + 1) * sizeof(WCHAR)));
     261        if (lrc != ERROR_SUCCESS)
     262            ErrorMsgLStatus("RegSetValueExW", lrc);
     263
     264        /*
     265         * Execute the SoftwareSettings section of the INF-file or something like that.
     266         */
     267        BOOL fOkay = FALSE;
     268        WCHAR wszSoftwareSection[LINE_LEN + 32];
     269        rc = RTUtf16Copy(wszSoftwareSection, RT_ELEMENTS(wszSoftwareSection), wszServiceData);
     270        if (RT_SUCCESS(rc))
     271            rc = RTUtf16CatAscii(wszSoftwareSection, RT_ELEMENTS(wszSoftwareSection), ".SoftwareSettings");
     272        if (RT_SUCCESS(rc))
     273        {
     274            if (SetupInstallFromInfSectionW(NULL, hInf, wszSoftwareSection, SPINST_REGISTRY, hKey,
     275                                            NULL, 0, NULL, NULL, NULL, NULL))
     276                fOkay = TRUE;
     277            else
     278                ErrorMsgLastErr("SetupInstallFromInfSectionW");
     279        }
     280        else
     281            ErrorMsg("Software settings section name too long");
     282        RegCloseKey(hKey);
     283        if (!fOkay)
     284            return RTEXITCODE_FAILURE;
     285    }
     286    else
     287        ErrorMsgLStatus("RegCreateKeyExW/Service", lrc);
     288
     289    /*
     290     * Install OpenGL stuff.
     291     */
     292    lrc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers", 0, NULL,
     293                          REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwIgn);
     294    if (lrc == ERROR_SUCCESS)
     295    {
     296        /* Do installation here if ever necessary. Currently there is no OpenGL stuff */
     297        RegCloseKey(hKey);
     298    }
     299    else
     300        ErrorMsgLStatus("RegCreateKeyExW/OpenGLDrivers", lrc);
     301
     302#if 0
     303    /* If this key is inserted into the registry, windows will show the desktop
     304       applet on next boot. We decide in the installer if we want that so the code
     305       is disabled here. */
     306    lrc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay",
     307                          0, NULL, REG_OPTION_NON_VOLATILE,
     308                          KEY_READ | KEY_WRITE, NULL, &hHey, &dwIgn)
     309    if (lrc == ERROR_SUCCESS)
     310        RegCloseKey(hHey);
     311    else
     312        ErrorMsgLStatus("RegCreateKeyExW/NewDisplay", lrc);
     313#endif
     314
     315    /*
     316     * We must reboot at some point
     317     */
     318    lrc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary", 0, NULL,
     319                          REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwIgn);
     320    if (lrc == ERROR_SUCCESS)
     321        RegCloseKey(hKey);
     322    else
     323        ErrorMsgLStatus("RegCreateKeyExW/RebootNecessary", lrc);
     324
     325    return RTEXITCODE_SUCCESS;
     326}
     327
    59328
    60329
     
    62331 * Install the VBox video driver.
    63332 *
    64  * @returns TRUE on success.
    65  * @returns FALSE on failure.
    66  * @param   szDriverDir     The base directory where we find the INF.
     333 * @param   pwszDriverDir     The base directory where we find the INF.
    67334 */
    68 BOOL installVideoDriver(TCHAR* szDriverDir)
    69 {
    70   HDEVINFO hDevInfo;
    71   SP_DEVINSTALL_PARAMS DeviceInstallParams={0};
    72   SP_DRVINFO_DATA drvInfoData={0};
    73   SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0};
    74 
    75   DWORD cbReqSize;
    76 
    77   /* Vars used for reading the INF */
    78   HINF hInf;
    79   TCHAR szServiceSection[LINE_LEN];
    80   INFCONTEXT serviceContext;
    81   TCHAR szServiceData[LINE_LEN];
    82   TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody...
    83 
    84   SP_DEVINFO_DATA deviceInfoData;
    85   DWORD configFlags;
    86 
    87   HKEY hkey;
    88   DWORD disp;
    89   TCHAR regKeyName[LINE_LEN];
    90 
    91   BOOL rc;
    92 
    93   /* Create an empty list */
    94   hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY,
    95                                          NULL);
    96 
    97   if (hDevInfo == INVALID_HANDLE_VALUE)
    98     return FALSE;
    99 
    100   memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
    101   DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
    102 
    103   rc=SetupDiGetDeviceInstallParams(hDevInfo,
    104                                    NULL,
    105                                    &DeviceInstallParams);
    106 
    107   if(!rc)
    108     return FALSE;
    109 
    110   DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
    111   DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */
    112     DI_DONOTCALLCONFIGMG |
    113     DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */
    114 
    115 
    116   /* Path to inf file */
    117   wsprintf(DeviceInstallParams.DriverPath,
    118            TEXT("%ws\\%ws"),
    119            szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
    120 
    121   rc=SetupDiSetDeviceInstallParams(hDevInfo,
    122                                    NULL,
    123                                    &DeviceInstallParams);
    124   if(!rc)
    125     return FALSE;
    126 
    127   /* Read the drivers from the inf file */
    128   if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
    129     {
    130       SetupDiDestroyDeviceInfoList(hDevInfo);
    131       return FALSE;
    132     }
    133 
    134   /* Get the first found driver.
    135      Our Inf file only contains one so this is fine  */
    136   drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
    137   if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
    138                                   0, &drvInfoData)){
     335static RTEXITCODE InstallVideoDriver(WCHAR const * const pwszDriverDir)
     336{
     337    /*
     338     * Create an empty list
     339     */
     340    HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_DISPLAY, NULL);
     341    if (hDevInfo == INVALID_HANDLE_VALUE)
     342        return ErrorMsgLastErr("SetupDiCreateDeviceInfoList");
     343
     344    /*
     345     * Get the default install parameters.
     346     */
     347    RTEXITCODE rcExit = RTEXITCODE_FAILURE;
     348    SP_DEVINSTALL_PARAMS_W DeviceInstallParams = { sizeof(SP_DEVINSTALL_PARAMS) };
     349    if (SetupDiGetDeviceInstallParamsW(hDevInfo, NULL, &DeviceInstallParams))
     350    {
     351        /*
     352         * Insert our install parameters and update hDevInfo with them.
     353         */
     354        DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
     355        DeviceInstallParams.Flags |= DI_NOFILECOPY /* We did our own file copying */
     356                                   | DI_DONOTCALLCONFIGMG
     357                                   | DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */
     358        int rc = RTUtf16Copy(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath), pwszDriverDir);
     359        if (RT_SUCCESS(rc))
     360            rc = RTUtf16CatAscii(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath),
     361                                 VBOXGUEST_VIDEO_INF_NAME);
     362        if (RT_SUCCESS(rc))
     363        {
     364            if (SetupDiSetDeviceInstallParamsW(hDevInfo, NULL, &DeviceInstallParams))
     365            {
     366                /*
     367                 * Read the drivers from the INF-file.
     368                 */
     369                if (SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
     370                {
     371                    HINF hInf = NULL;
     372                    rcExit = InstallVideoDriverInner(pwszDriverDir, hDevInfo, &hInf);
     373
     374                    if (hInf)
     375                        SetupCloseInfFile(hInf);
     376                    SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
     377                }
     378                else
     379                    ErrorMsgLastErr("SetupDiBuildDriverInfoList");
     380            }
     381            else
     382                ErrorMsgLastErr("SetupDiSetDeviceInstallParamsW");
     383
     384        }
     385        else
     386            ErrorMsg("Install dir too deep (long)");
     387        SetupDiDestroyDeviceInfoList(hDevInfo);
     388    }
     389    else
     390        ErrorMsgLastErr("SetupDiGetDeviceInstallParams"); /** @todo Original code didn't return here. */
    139391    SetupDiDestroyDeviceInfoList(hDevInfo);
    140     return FALSE;
    141   }
    142 
    143   /* Get necessary driver details */
    144   DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
    145   if (!(!SetupDiGetDriverInfoDetail(hDevInfo,
    146                                     NULL,
    147                                     &drvInfoData,
    148                                     &DriverInfoDetailData,
    149                                     DriverInfoDetailData.cbSize,
    150                                     &cbReqSize)
    151         &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) )
    152     {
    153       SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
    154       SetupDiDestroyDeviceInfoList(hDevInfo);
    155       return FALSE;
    156     }
    157 
    158   hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
    159                           NULL, INF_STYLE_WIN4, NULL);
    160 
    161   if (hInf == INVALID_HANDLE_VALUE)
    162     {
    163       SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
    164       SetupDiDestroyDeviceInfoList(hDevInfo);
    165       return FALSE;
    166     }
    167 
    168   /* First install the service */
    169   wsprintf(szServiceSection, TEXT("%ws.Services"),
    170            DriverInfoDetailData.SectionName);
    171 
    172   if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext))
    173     {
    174       /* No service line?? Can't be... */
    175       closeAndDestroy(hDevInfo, hInf);
    176       return FALSE;
    177     }
    178 
    179   /* Get the name */
    180   SetupGetStringField(&serviceContext,
    181                       1,
    182                       szServiceData,
    183                       sizeof(szServiceData),
    184                       NULL);
    185 
    186   wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData);
    187 
    188   memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
    189   deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    190 
    191   if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing
    192       ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr,                      //Create new
    193                                  (LPGUID) &GUID_DEVCLASS_DISPLAY,
    194                                  NULL, //Do we need a description here?
    195                                  NULL, //No user interface
    196                                  0,
    197                                  &deviceInfoData) &&
    198          SetupDiRegisterDeviceInfo(hDevInfo,
    199                                    &deviceInfoData,
    200                                    0,
    201                                    NULL,
    202                                    NULL,
    203                                    NULL)) )
    204     {
    205       /* We created a new key in the registry */
    206 
    207       memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS));
    208       DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
    209 
    210       SetupDiGetDeviceInstallParams(hDevInfo,
    211                                     &deviceInfoData,
    212                                     &DeviceInstallParams);
    213 
    214       DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files
    215         DI_DONOTCALLCONFIGMG |
    216         DI_ENUMSINGLEINF; //Use our INF file only
    217 
    218       /* Path to inf file */
    219       wsprintf(DeviceInstallParams.DriverPath,
    220                TEXT("%ws\\%ws"),
    221                szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
    222 
    223       SetupDiSetDeviceInstallParams(hDevInfo,
    224                                     &deviceInfoData,
    225                                     &DeviceInstallParams);
    226 
    227 
    228       if(!SetupDiBuildDriverInfoList(hDevInfo,
    229                                      &deviceInfoData,
    230                                      SPDIT_CLASSDRIVER))
     392    return rcExit;
     393}
     394
     395
     396/**
     397 * Video driver uninstallation will be added later if necessary.
     398 */
     399static RTEXITCODE UninstallDrivers(void)
     400{
     401    return ErrorMsg("Uninstall not implemented");
     402}
     403
     404
     405static RTEXITCODE displayHelpAndExit(char *pszProgName)
     406{
     407    HANDLE const hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
     408    DWORD        cbIgn;
     409    WriteFile(hStdOut, RT_STR_TUPLE("Installs VirtualBox Guest Additions Graphics Drivers for Windows NT 4.0\r\n"
     410                                    "\r\n"
     411                                    "Syntax: "), &cbIgn, NULL);
     412    WriteFile(hStdOut, pszProgName, (DWORD)strlen(pszProgName), &cbIgn, NULL);
     413    WriteFile(hStdOut, RT_STR_TUPLE("</i|/u>\r\n"
     414                                    "\r\n"
     415                                    "Options:\r\n"
     416                                    "    /i - Install draphics drivers\r\n"
     417                                    "    /u - Uninstall draphics drivers (not implemented)\r\n"
     418                                    ), &cbIgn, NULL);
     419    return RTEXITCODE_SYNTAX;
     420}
     421
     422
     423static bool IsNt4(void)
     424{
     425    OSVERSIONINFOW VerInfo = { sizeof(VerInfo), 0 };
     426    GetVersionExW(&VerInfo);
     427    return VerInfo.dwPlatformId  == VER_PLATFORM_WIN32_NT
     428        && VerInfo.dwMajorVersion == 4;
     429}
     430
     431
     432int main(int argc, char **argv)
     433{
     434    /*
     435     * "Parse" arguments
     436     */
     437    if (argc != 2)
     438    {
     439        if (argc > 2)
     440            ErrorMsg("Too many parameter. Expected only one.");
     441        return displayHelpAndExit(argv[0]);
     442    }
     443
     444    bool        fInstall = true;
     445    const char *pszArg   = argv[1];
     446    if (RTStrICmpAscii(pszArg, "/i") == 0)
     447        fInstall = true;
     448    else if (RTStrICmpAscii(pszArg, "/u") == 0)
     449        fInstall = false;
     450    else
     451    {
     452        ErrorMsg("Unknown parameter (only known parameters are '/i' and '/u')");
     453        ErrorMsg(pszArg);
     454        return displayHelpAndExit(argv[0]);
     455    }
     456
     457    /*
     458     * This program is only for installing drivers on NT4.
     459     */
     460    RTEXITCODE rcExit = RTEXITCODE_FAILURE;
     461    if (IsNt4())
     462    {
     463        /*
     464         * Derive the installation directory from the executable location.
     465         * Just strip the filename and use the path.
     466         */
     467        WCHAR wszInstallDir[MAX_PATH];
     468        DWORD cwcInstallDir = GetModuleFileNameW(GetModuleHandle(NULL), &wszInstallDir[0], RT_ELEMENTS(wszInstallDir));
     469        if (cwcInstallDir > 0)
    231470        {
    232           closeAndDestroy(hDevInfo, hInf);
    233           return FALSE;
     471            while (cwcInstallDir > 0 && RTPATH_IS_SEP(wszInstallDir[cwcInstallDir - 1]))
     472                cwcInstallDir--;
     473            if (!cwcInstallDir) /* paranoia^3 */
     474            {
     475                wszInstallDir[cwcInstallDir++] = '.';
     476                wszInstallDir[cwcInstallDir++] = '\\';
     477            }
     478            wszInstallDir[cwcInstallDir] = '\0';
     479
     480            /*
     481             * Do the install/uninstall.
     482             */
     483            if (fInstall)
     484                rcExit = InstallVideoDriver(wszInstallDir);
     485            else
     486                rcExit = UninstallDrivers();
     487
     488            /*
     489             * Summary message.
     490             */
     491            if (rcExit != RTEXITCODE_SUCCESS)
     492                ErrorMsg("Some failure occurred during driver installation");
    234493        }
    235 
    236       drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
    237       if (!SetupDiEnumDriverInfo(hDevInfo,
    238                                  &deviceInfoData,
    239                                  SPDIT_CLASSDRIVER,
    240                                  0,
    241                                  &drvInfoData))
    242         {
    243           closeAndDestroy(hDevInfo, hInf);
    244           return FALSE;
    245         }
    246 
    247       if(!SetupDiSetSelectedDriver(hDevInfo,
    248                                    &deviceInfoData,
    249                                    &drvInfoData))
    250         {
    251           closeAndDestroy(hDevInfo, hInf);
    252           return FALSE;
    253         }
    254 
    255       if(!SetupDiInstallDevice(hDevInfo,
    256                                &deviceInfoData))
    257         {
    258           closeAndDestroy(hDevInfo, hInf);
    259           return FALSE;
    260         }
    261     }
    262 
    263   /* Make sure the device is enabled */
    264   if (SetupDiGetDeviceRegistryProperty(hDevInfo,
    265                                        &deviceInfoData, SPDRP_CONFIGFLAGS,
    266                                        NULL, (LPBYTE) &configFlags,
    267                                        sizeof(DWORD),
    268                                        NULL)
    269       && (configFlags & CONFIGFLAG_DISABLED))
    270     {
    271       configFlags &= ~CONFIGFLAG_DISABLED;
    272 
    273       SetupDiSetDeviceRegistryProperty(hDevInfo,
    274                                        &deviceInfoData,
    275                                        SPDRP_CONFIGFLAGS,
    276                                        (LPBYTE) &configFlags,
    277                                        sizeof(DWORD));
    278     }
    279 
    280   wsprintf(regKeyName,
    281            TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"),
    282            szServiceData, 0); //We only have one device
    283 
    284   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
    285                      regKeyName,
    286                      0,
    287                      NULL,
    288                      REG_OPTION_NON_VOLATILE,
    289                      KEY_READ | KEY_WRITE,
    290                      NULL,
    291                      &hkey,
    292                      &disp) == ERROR_SUCCESS)
    293     {
    294       /* Insert description */
    295       RegSetValueEx(hkey,
    296                     TEXT("Device Description"),
    297                     0,
    298                     REG_SZ,
    299                     (LPBYTE) DriverInfoDetailData.DrvDescription,
    300                     (lstrlen(DriverInfoDetailData.DrvDescription) + 1) *
    301                     sizeof(TCHAR) );
    302 
    303       TCHAR szSoftwareSection[LINE_LEN];
    304 
    305       wsprintf(szSoftwareSection,
    306                TEXT("%ws.SoftwareSettings"),
    307                szServiceData);
    308 
    309       if (!SetupInstallFromInfSection(NULL,
    310                                       hInf,
    311                                       szSoftwareSection,
    312                                       SPINST_REGISTRY,
    313                                       hkey,
    314                                       NULL,
    315                                       0,
    316                                       NULL,
    317                                       NULL,
    318                                       NULL,
    319                                       NULL))
    320         {
    321           RegCloseKey(hkey);
    322           closeAndDestroy(hDevInfo, hInf);
    323           return FALSE;
    324         }
    325 
    326       RegCloseKey(hkey);
    327     }
    328 
    329   /* Install OpenGL stuff */
    330   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
    331                      TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"),
    332                      0,
    333                      NULL,
    334                      REG_OPTION_NON_VOLATILE,
    335                      KEY_READ | KEY_WRITE,
    336                      NULL,
    337                      &hkey,
    338                      &disp) == ERROR_SUCCESS)
    339     {
    340       /* Do installation here if ever necessary. Currently there is no OpenGL stuff */
    341 
    342       RegCloseKey(hkey);
    343     }
    344 
    345 
    346   /* Cleanup */
    347   closeAndDestroy(hDevInfo, hInf);
    348 
    349 #if 0
    350   /* If this key is inserted into the registry, windows will show the desktop
    351      applet on next boot. We decide in the installer if we want that so the code
    352      is disabled here. */
    353   /* Set registry keys so windows picks up the changes */
    354   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
    355                      TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"),
    356                      0,
    357                      NULL,
    358                      REG_OPTION_NON_VOLATILE,
    359                      KEY_READ | KEY_WRITE,
    360                      NULL,
    361                      &hkey,
    362                      &disp) == ERROR_SUCCESS)
    363     {
    364       RegCloseKey(hkey);
    365     }
    366 #endif
    367 
    368   /* We must reboot at some point */
    369   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
    370                      TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"),
    371                      0,
    372                      NULL,
    373                      REG_OPTION_NON_VOLATILE,
    374                      KEY_READ | KEY_WRITE,
    375                      NULL,
    376                      &hkey,
    377                      &disp) == ERROR_SUCCESS)
    378     {
    379       RegCloseKey(hkey);
    380     }
    381 
    382   return TRUE;
    383 }
    384 
    385 
    386 void displayHelpAndExit(char *programName)
    387 {
    388     printf("Installs VirtualBox Guest Additions for Windows NT 4.0\n\n");
    389     printf("Syntax: %s [/i|/u]\n", programName);
    390     printf("\n\t/i  - perform Guest Additions installation\n");
    391     printf("\t/u:  - perform Guest Additions uninstallation\n");
    392     exit(1);
    393 }
    394 
    395 /**
    396  * Check if we are running on NT4.
    397  *
    398  * @returns TRUE if NT 4.
    399  * @returns FALSE otherwise.
    400  */
    401 BOOL isNT4(void)
    402 {
    403     OSVERSIONINFO osVersion;
    404 
    405     osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    406     GetVersionEx(&osVersion);
    407 
    408     switch (osVersion.dwPlatformId)
    409     {
    410         case VER_PLATFORM_WIN32s:
    411         case VER_PLATFORM_WIN32_WINDOWS:
    412             return FALSE;
    413         case VER_PLATFORM_WIN32_NT:
    414             if (osVersion.dwMajorVersion == 4)
    415                 return TRUE;
    416             else
    417                 return FALSE;
    418         default:
    419             break;
    420     }
    421     return FALSE;
    422 }
    423 
    424 /**
    425  *  Video driver uninstallation will be added later if necessary.
    426  */
    427 int uninstallDrivers(void)
    428 {
    429     return 0;
    430 }
    431 
    432 
    433 int main(int argc, char **argv)
    434 {
    435     BOOL rc=FALSE;
    436     TCHAR szInstallDir[MAX_PATH];
    437     HMODULE hExe = GetModuleHandle(NULL);
    438 
    439   /** @todo r=bird:
    440    * And by the way, we're only missing the coding style dmik uses now
    441    * and this file would contain the complete set.  */
    442   if(2!=argc || (stricmp(argv[1], "/i") && stricmp(argv[1], "/u")))
    443     displayHelpAndExit(argv[0]);
    444 
    445   /* This program is only for installing drivers on NT4 */
    446   if(!isNT4()){
    447     printf("This program only runs on NT4\n");
    448     return -1;
    449   }
    450 
    451   if (!GetModuleFileName(hExe, &szInstallDir[0], sizeof(szInstallDir)))
    452     {
    453       printf("GetModuleFileName failed! rc=%lu\n", GetLastError());
    454       return -1;
    455     }
    456 
    457   TCHAR *lastBackslash = wcsrchr(szInstallDir, L'\\');
    458 
    459   if (!lastBackslash)
    460     {
    461       printf("Invalid path name!\n");
    462       return -1;
    463     }
    464 
    465   *lastBackslash=L'\0';
    466 
    467   /* Install video driver. Mouse driver installation is done by overwriting
    468      the image path in the setup script. */
    469   if(!stricmp(argv[1], "/i")){
    470     rc=installVideoDriver(szInstallDir);
    471   }
    472   else{
    473     /* No video driver uninstallation yet. Do we need it? */
    474   }
    475 
    476   if(FALSE==rc)
    477     printf("Some failure occurred during driver installation.\n");
    478   return !rc; /* Return != 0 on failure. */
    479 }
     494        else
     495            ErrorMsgLastErr("GetModuleFileNameW failed!");
     496    }
     497    else
     498        ErrorMsg("This program only runs on NT4");
     499    return rcExit;
     500}
     501
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