78a072e1b56619e3230735ae073668311232ec94vboxsync/** @file
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * instdrvmain - Install guest drivers on NT4
78a072e1b56619e3230735ae073668311232ec94vboxsync *
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2010 Oracle Corporation
78a072e1b56619e3230735ae073668311232ec94vboxsync *
2f139cbf73f9adba01382892f33558ad7bcb40cbvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2f139cbf73f9adba01382892f33558ad7bcb40cbvboxsync * available from http://www.virtualbox.org. This file is free software;
2f139cbf73f9adba01382892f33558ad7bcb40cbvboxsync * you can redistribute it and/or modify it under the terms of the GNU
2f139cbf73f9adba01382892f33558ad7bcb40cbvboxsync * General Public License (GPL) as published by the Free Software
2f139cbf73f9adba01382892f33558ad7bcb40cbvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2f139cbf73f9adba01382892f33558ad7bcb40cbvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2f139cbf73f9adba01382892f33558ad7bcb40cbvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * @todo
78a072e1b56619e3230735ae073668311232ec94vboxsync * The spacing in this file is horrible! Here are some simple rules:
78a072e1b56619e3230735ae073668311232ec94vboxsync * - tabs are forbidden
78a072e1b56619e3230735ae073668311232ec94vboxsync * - indentation is 4 spaces
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <windows.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <setupapi.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <regstr.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <DEVGUID.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <stdio.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync#include "tchar.h"
78a072e1b56619e3230735ae073668311232ec94vboxsync#include "string.h"
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/*******************************************************************************
78a072e1b56619e3230735ae073668311232ec94vboxsync* Defined Constants And Macros *
78a072e1b56619e3230735ae073668311232ec94vboxsync*******************************************************************************/
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/** The video service name. */
78a072e1b56619e3230735ae073668311232ec94vboxsync#define VBOXGUEST_VIDEO_NAME "VBoxVideo"
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/** The video inf file name */
78a072e1b56619e3230735ae073668311232ec94vboxsync#define VBOXGUEST_VIDEO_INF_NAME "VBoxVideo.inf"
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/////////////////////////////////////////////////////////////////////////////
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Do some cleanup of data we used. Called by installVideoDriver()
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncvoid closeAndDestroy(HDEVINFO hDevInfo, HINF hInf)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDeviceInfoList(hDevInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupCloseInfFile(hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Install the VBox video driver.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns TRUE on success.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns FALSE on failure.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param szDriverDir The base directory where we find the INF.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncBOOL installVideoDriver(TCHAR* szDriverDir)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync HDEVINFO hDevInfo;
78a072e1b56619e3230735ae073668311232ec94vboxsync SP_DEVINSTALL_PARAMS DeviceInstallParams={0};
78a072e1b56619e3230735ae073668311232ec94vboxsync SP_DRVINFO_DATA drvInfoData={0};
78a072e1b56619e3230735ae073668311232ec94vboxsync SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0};
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync DWORD cbReqSize;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Vars used for reading the INF */
78a072e1b56619e3230735ae073668311232ec94vboxsync HINF hInf;
78a072e1b56619e3230735ae073668311232ec94vboxsync TCHAR szServiceSection[LINE_LEN];
78a072e1b56619e3230735ae073668311232ec94vboxsync INFCONTEXT serviceContext;
78a072e1b56619e3230735ae073668311232ec94vboxsync TCHAR szServiceData[LINE_LEN];
78a072e1b56619e3230735ae073668311232ec94vboxsync TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody...
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync SP_DEVINFO_DATA deviceInfoData;
78a072e1b56619e3230735ae073668311232ec94vboxsync DWORD configFlags;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync HKEY hkey;
78a072e1b56619e3230735ae073668311232ec94vboxsync DWORD disp;
78a072e1b56619e3230735ae073668311232ec94vboxsync TCHAR regKeyName[LINE_LEN];
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync BOOL rc;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Create an empty list */
78a072e1b56619e3230735ae073668311232ec94vboxsync hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if (hDevInfo == INVALID_HANDLE_VALUE)
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
78a072e1b56619e3230735ae073668311232ec94vboxsync DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync rc=SetupDiGetDeviceInstallParams(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync &DeviceInstallParams);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!rc)
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
78a072e1b56619e3230735ae073668311232ec94vboxsync DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */
78a072e1b56619e3230735ae073668311232ec94vboxsync DI_DONOTCALLCONFIGMG |
78a072e1b56619e3230735ae073668311232ec94vboxsync DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Path to inf file */
78a072e1b56619e3230735ae073668311232ec94vboxsync wsprintf(DeviceInstallParams.DriverPath,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("%ws\\%ws"),
78a072e1b56619e3230735ae073668311232ec94vboxsync szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync rc=SetupDiSetDeviceInstallParams(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync &DeviceInstallParams);
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!rc)
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Read the drivers from the inf file */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDeviceInfoList(hDevInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Get the first found driver.
78a072e1b56619e3230735ae073668311232ec94vboxsync Our Inf file only contains one so this is fine */
78a072e1b56619e3230735ae073668311232ec94vboxsync drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
78a072e1b56619e3230735ae073668311232ec94vboxsync if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
78a072e1b56619e3230735ae073668311232ec94vboxsync 0, &drvInfoData)){
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDeviceInfoList(hDevInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Get necessary driver details */
78a072e1b56619e3230735ae073668311232ec94vboxsync DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!(!SetupDiGetDriverInfoDetail(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync &drvInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync &DriverInfoDetailData,
78a072e1b56619e3230735ae073668311232ec94vboxsync DriverInfoDetailData.cbSize,
78a072e1b56619e3230735ae073668311232ec94vboxsync &cbReqSize)
78a072e1b56619e3230735ae073668311232ec94vboxsync &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) )
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDeviceInfoList(hDevInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL, INF_STYLE_WIN4, NULL);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if (hInf == INVALID_HANDLE_VALUE)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiDestroyDeviceInfoList(hDevInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* First install the service */
78a072e1b56619e3230735ae073668311232ec94vboxsync wsprintf(szServiceSection, TEXT("%ws.Services"),
78a072e1b56619e3230735ae073668311232ec94vboxsync DriverInfoDetailData.SectionName);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync /* No service line?? Can't be... */
78a072e1b56619e3230735ae073668311232ec94vboxsync closeAndDestroy(hDevInfo, hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Get the name */
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupGetStringField(&serviceContext,
78a072e1b56619e3230735ae073668311232ec94vboxsync 1,
78a072e1b56619e3230735ae073668311232ec94vboxsync szServiceData,
78a072e1b56619e3230735ae073668311232ec94vboxsync sizeof(szServiceData),
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
78a072e1b56619e3230735ae073668311232ec94vboxsync deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing
78a072e1b56619e3230735ae073668311232ec94vboxsync ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr, //Create new
78a072e1b56619e3230735ae073668311232ec94vboxsync (LPGUID) &GUID_DEVCLASS_DISPLAY,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL, //Do we need a description here?
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL, //No user interface
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData) &&
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiRegisterDeviceInfo(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL)) )
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync /* We created a new key in the registry */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS));
78a072e1b56619e3230735ae073668311232ec94vboxsync DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiGetDeviceInstallParams(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync &DeviceInstallParams);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files
78a072e1b56619e3230735ae073668311232ec94vboxsync DI_DONOTCALLCONFIGMG |
78a072e1b56619e3230735ae073668311232ec94vboxsync DI_ENUMSINGLEINF; //Use our INF file only
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Path to inf file */
78a072e1b56619e3230735ae073668311232ec94vboxsync wsprintf(DeviceInstallParams.DriverPath,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("%ws\\%ws"),
78a072e1b56619e3230735ae073668311232ec94vboxsync szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiSetDeviceInstallParams(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync &DeviceInstallParams);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!SetupDiBuildDriverInfoList(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync SPDIT_CLASSDRIVER))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync closeAndDestroy(hDevInfo, hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!SetupDiEnumDriverInfo(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync SPDIT_CLASSDRIVER,
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync &drvInfoData))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync closeAndDestroy(hDevInfo, hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!SetupDiSetSelectedDriver(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync &drvInfoData))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync closeAndDestroy(hDevInfo, hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!SetupDiInstallDevice(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync closeAndDestroy(hDevInfo, hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Make sure the device is enabled */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (SetupDiGetDeviceRegistryProperty(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData, SPDRP_CONFIGFLAGS,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL, (LPBYTE) &configFlags,
78a072e1b56619e3230735ae073668311232ec94vboxsync sizeof(DWORD),
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL)
78a072e1b56619e3230735ae073668311232ec94vboxsync && (configFlags & CONFIGFLAG_DISABLED))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync configFlags &= ~CONFIGFLAG_DISABLED;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync SetupDiSetDeviceRegistryProperty(hDevInfo,
78a072e1b56619e3230735ae073668311232ec94vboxsync &deviceInfoData,
78a072e1b56619e3230735ae073668311232ec94vboxsync SPDRP_CONFIGFLAGS,
78a072e1b56619e3230735ae073668311232ec94vboxsync (LPBYTE) &configFlags,
78a072e1b56619e3230735ae073668311232ec94vboxsync sizeof(DWORD));
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync wsprintf(regKeyName,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"),
78a072e1b56619e3230735ae073668311232ec94vboxsync szServiceData, 0); //We only have one device
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
78a072e1b56619e3230735ae073668311232ec94vboxsync regKeyName,
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync REG_OPTION_NON_VOLATILE,
78a072e1b56619e3230735ae073668311232ec94vboxsync KEY_READ | KEY_WRITE,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync &hkey,
78a072e1b56619e3230735ae073668311232ec94vboxsync &disp) == ERROR_SUCCESS)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Insert description */
78a072e1b56619e3230735ae073668311232ec94vboxsync RegSetValueEx(hkey,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("Device Description"),
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync REG_SZ,
78a072e1b56619e3230735ae073668311232ec94vboxsync (LPBYTE) DriverInfoDetailData.DrvDescription,
78a072e1b56619e3230735ae073668311232ec94vboxsync (lstrlen(DriverInfoDetailData.DrvDescription) + 1) *
78a072e1b56619e3230735ae073668311232ec94vboxsync sizeof(TCHAR) );
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync TCHAR szSoftwareSection[LINE_LEN];
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync wsprintf(szSoftwareSection,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("%ws.SoftwareSettings"),
78a072e1b56619e3230735ae073668311232ec94vboxsync szServiceData);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!SetupInstallFromInfSection(NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync hInf,
78a072e1b56619e3230735ae073668311232ec94vboxsync szSoftwareSection,
78a072e1b56619e3230735ae073668311232ec94vboxsync SPINST_REGISTRY,
78a072e1b56619e3230735ae073668311232ec94vboxsync hkey,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync RegCloseKey(hkey);
78a072e1b56619e3230735ae073668311232ec94vboxsync closeAndDestroy(hDevInfo, hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync RegCloseKey(hkey);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Install OpenGL stuff */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"),
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync REG_OPTION_NON_VOLATILE,
78a072e1b56619e3230735ae073668311232ec94vboxsync KEY_READ | KEY_WRITE,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync &hkey,
78a072e1b56619e3230735ae073668311232ec94vboxsync &disp) == ERROR_SUCCESS)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Do installation here if ever necessary. Currently there is no OpenGL stuff */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync RegCloseKey(hkey);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Cleanup */
78a072e1b56619e3230735ae073668311232ec94vboxsync closeAndDestroy(hDevInfo, hInf);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync#if 0
78a072e1b56619e3230735ae073668311232ec94vboxsync /* If this key is inserted into the registry, windows will show the desktop
78a072e1b56619e3230735ae073668311232ec94vboxsync applet on next boot. We decide in the installer if we want that so the code
78a072e1b56619e3230735ae073668311232ec94vboxsync is disabled here. */
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Set registry keys so windows picks up the changes */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"),
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync REG_OPTION_NON_VOLATILE,
78a072e1b56619e3230735ae073668311232ec94vboxsync KEY_READ | KEY_WRITE,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync &hkey,
78a072e1b56619e3230735ae073668311232ec94vboxsync &disp) == ERROR_SUCCESS)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync RegCloseKey(hkey);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync#endif
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* We must reboot at some point */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
78a072e1b56619e3230735ae073668311232ec94vboxsync TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"),
78a072e1b56619e3230735ae073668311232ec94vboxsync 0,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync REG_OPTION_NON_VOLATILE,
78a072e1b56619e3230735ae073668311232ec94vboxsync KEY_READ | KEY_WRITE,
78a072e1b56619e3230735ae073668311232ec94vboxsync NULL,
78a072e1b56619e3230735ae073668311232ec94vboxsync &hkey,
78a072e1b56619e3230735ae073668311232ec94vboxsync &disp) == ERROR_SUCCESS)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync RegCloseKey(hkey);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync return TRUE;
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsyncvoid displayHelpAndExit(char *programName)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("Installs VirtualBox Guest Additions for Windows NT 4.0\n\n");
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("Syntax: %s [/i|/u]\n", programName);
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("\n\t/i - perform Guest Additions installation\n");
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("\t/u: - perform Guest Additions uninstallation\n");
78a072e1b56619e3230735ae073668311232ec94vboxsync exit(1);
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Check if we are running on NT4.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns TRUE if NT 4.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns FALSE otherwise.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncBOOL isNT4(void)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync OSVERSIONINFO osVersion;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
78a072e1b56619e3230735ae073668311232ec94vboxsync GetVersionEx(&osVersion);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync switch (osVersion.dwPlatformId)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync case VER_PLATFORM_WIN32s:
78a072e1b56619e3230735ae073668311232ec94vboxsync case VER_PLATFORM_WIN32_WINDOWS:
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync case VER_PLATFORM_WIN32_NT:
78a072e1b56619e3230735ae073668311232ec94vboxsync if (osVersion.dwMajorVersion == 4)
78a072e1b56619e3230735ae073668311232ec94vboxsync return TRUE;
78a072e1b56619e3230735ae073668311232ec94vboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync default:
78a072e1b56619e3230735ae073668311232ec94vboxsync break;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync return FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Video driver uninstallation will be added later if necessary.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncint uninstallDrivers(void)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync return 0;
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsyncint main(int argc, char **argv)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync BOOL rc=FALSE;
78a072e1b56619e3230735ae073668311232ec94vboxsync TCHAR szInstallDir[MAX_PATH];
78a072e1b56619e3230735ae073668311232ec94vboxsync HMODULE hExe = GetModuleHandle(NULL);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /** @todo r=bird:
78a072e1b56619e3230735ae073668311232ec94vboxsync * And by the way, we're only missing the coding style dmik uses now
78a072e1b56619e3230735ae073668311232ec94vboxsync * and this file would contain the complete set. */
78a072e1b56619e3230735ae073668311232ec94vboxsync if(2!=argc || (stricmp(argv[1], "/i") && stricmp(argv[1], "/u")))
78a072e1b56619e3230735ae073668311232ec94vboxsync displayHelpAndExit(argv[0]);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* This program is only for installing drivers on NT4 */
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!isNT4()){
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("This program only runs on NT4\n");
78a072e1b56619e3230735ae073668311232ec94vboxsync return -1;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!GetModuleFileName(hExe, &szInstallDir[0], sizeof(szInstallDir)))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("GetModuleFileName failed! rc = %d\n", GetLastError());
78a072e1b56619e3230735ae073668311232ec94vboxsync return -1;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync TCHAR *lastBackslash = wcsrchr(szInstallDir, L'\\');
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!lastBackslash)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("Invalid path name!\n");
78a072e1b56619e3230735ae073668311232ec94vboxsync return -1;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync *lastBackslash=L'\0';
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Install video driver. Mouse driver installation is done by overwriting
78a072e1b56619e3230735ae073668311232ec94vboxsync the image path in the setup script. */
78a072e1b56619e3230735ae073668311232ec94vboxsync if(!stricmp(argv[1], "/i")){
78a072e1b56619e3230735ae073668311232ec94vboxsync rc=installVideoDriver(szInstallDir);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync else{
78a072e1b56619e3230735ae073668311232ec94vboxsync /* No video driver uninstallation yet. Do we need it? */
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if(FALSE==rc)
78a072e1b56619e3230735ae073668311232ec94vboxsync printf("Some failure occurred during driver installation.\n");
78a072e1b56619e3230735ae073668311232ec94vboxsync return !rc; /* Return != 0 on failure. */
78a072e1b56619e3230735ae073668311232ec94vboxsync}