protected void ProcessCoInstallersSection(PNPDriverINFFile pnpDriverInf, string installSectionName)
        {
            var matchingInstallSectionName = pnpDriverInf.GetMatchingInstallSectionName(installSectionName,
                                                                                        _architectureIdentifier, _minorOSVersion);

            if (matchingInstallSectionName == string.Empty)
            {
                return;
            }
            var matchingCoInstallersSectionName = matchingInstallSectionName + ".CoInstallers";
            var coinstallersSection             = pnpDriverInf.GetSection(matchingCoInstallersSectionName);

            foreach (var line in coinstallersSection)
            {
                var keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "CopyFiles":
                {
                    if (keyAndValues.Value[0].StartsWith("@"))
                    {
                        ProcessCopyFileDirective(pnpDriverInf, keyAndValues.Value[0].Substring(1));
                    }
                    else
                    {
                        foreach (var copyFilesSectionName in keyAndValues.Value)
                        {
                            ProcessCopyFilesSection(pnpDriverInf, copyFilesSectionName);
                        }
                    }
                    break;
                }
                }
            }
        }
Esempio n. 2
0
        private void PreconfigureDeviceInstance(PNPDriverINFFile pnpDriverInf, ISystemRegistryHive systemRegistryHive, string enumerator, string deviceID, string deviceInstanceID, BaseDeviceService deviceService)
        {
            var driver           = pnpDriverInf.ClassGUID.ToUpper() + @"\" + _classInstanceID;
            var manufacturerName = pnpDriverInf.GetDeviceManufacturerName(HardwareID, _installation.ArchitectureIdentifier, _installation.MinorOSVersion, _installation.ProductType);

            var hardwareKeyName = @"Enum\" + enumerator + @"\" + deviceID + @"\" + deviceInstanceID;

            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "ClassGUID", RegistryValueKind.String, pnpDriverInf.ClassGUID);
            // The presence of DeviceDesc is critical for some reason, but any value can be used
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "DeviceDesc", RegistryValueKind.String, deviceService.DeviceDescription);
            // "Driver" is used to help Windows determine which software key belong to this hardware key.
            // Note: When re-installing the driver, the software key to be used will be determined by this value as well.
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "Driver", RegistryValueKind.String, driver);
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "Service", RegistryValueKind.String, deviceService.ServiceName);

            // ConfigFlags is not related to the hardware, it's the status of the configuration of the device by Windows (CONFIGFLAG_FAILEDINSTALL etc.)
            // the presence of this value tells windows the device has driver installed
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "ConfigFlags", RegistryValueKind.DWord, 0);

            if (PNPDriverINFFile.IsRootDevice(HardwareID))
            {
                // Windows uses the "HardwareID" entry to determine if the hardware is already installed,
                // We don't have to add this value for physical devices, because Windows will get this value from the device,
                // but we must add this for virtual devices, or we will find ourselves with duplicity when re-installing (e.g. two Microsoft iScsi Initiators).
                systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "HardwareID", RegistryValueKind.MultiString,
                                                                   new[] { HardwareID });
            }

            // not necessary:
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "Mfg", RegistryValueKind.String, manufacturerName);
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "Class", RegistryValueKind.String, pnpDriverInf.ClassName);
        }
        // In-box device drivers = drivers that are shipped with Windows
        public static void DisableInBoxDeviceDrivers(string setupDirectory, string architectureIdentifier, int minorOSVersion, int productType, string hardwareID)
        {
            Console.WriteLine();
            Console.WriteLine("Looking for drivers for your device (" + hardwareID + ") in Windows setup directory (to disable them):");
            var filePaths = Directory.GetFiles(setupDirectory, "*.in_");

            foreach (var filePath in filePaths)
            {
                var packedFileName   = FileSystemUtils.GetNameFromPath(filePath);
                var unpackedFileName = packedFileName.Substring(0, packedFileName.Length - 1) + "F";                 // the filename inside the archive ends with .INF and not with .IN_

                var cabInfo = new CabInfo(filePath);

                ArchiveFileInfo fileInfo = null;
                try
                {
                    // some files do not contain an inf file
                    // for instance, netmon.in_ contains netmon.ini
                    fileInfo = cabInfo.GetFile(unpackedFileName);
                }
                catch (CabException ex)
                {
                    // file is invalid / unsupported
                    Console.WriteLine("Cannot examine file '{0}': {1}", packedFileName, ex.Message);
                }

                if (fileInfo != null)
                {
                    var driverInf = new PNPDriverINFFile(unpackedFileName);
                    try
                    {
                        driverInf.ReadPackedFromDirectory(setupDirectory);
                    }
                    catch (CabException ex)
                    {
                        // the archive is a cab and it contains the file we are looking for, but the file is corrupted
                        Console.WriteLine("Cannot unpack file '{0}': {1}", driverInf.PackedFileName, ex.Message);
                        continue;
                    }

                    // Windows will pick up it's own signed drivers even if the added driver also match the SUBSYS,
                    // so we have to disable in-box drivers regardless of the presence of &SUBSYS
                    var found = driverInf.DisableMatchingHardwareID(hardwareID, architectureIdentifier, minorOSVersion, productType);

                    if (found)
                    {
                        Console.WriteLine("Device driver for '{0}' found in file '{1}'.", hardwareID, packedFileName);
                        driverInf.SavePackedToDirectory(setupDirectory);
                    }
                }
            }
            Console.WriteLine("Finished looking for drivers for your device in Windows setup directory.");
        }
        private void ProcessCopyFileDirective(PNPDriverINFFile pnpDriverInf, string sourceFileName, string destinationFileName)
        {
            var relativeSourcePath = PNPDriverIntegratorUtils.GetRelativeDirectoryPath(pnpDriverInf, sourceFileName,
                                                                                       _architectureIdentifier);
            var fileToCopy = new FileToCopy(relativeSourcePath, sourceFileName, destinationFileName);

            if (!FileSystemUtils.IsFileExist(_driverDirectory.Path + fileToCopy.RelativeSourceFilePath))
            {
                Console.WriteLine("Error: Missing file: " + _driverDirectory.Path + fileToCopy.RelativeSourceFilePath);
                Program.Exit();
            }
            // actual copy will be performed later
            _driverFilesToCopy.Add(fileToCopy);
        }
        /// <param name="sectionName"></param>
        /// <param name="relativeRoot">
        /// The location where HKR entried will be stored, relative to 'SYSTEM\CurrentControlSet\' (or ControlSet001 for that matter)
        /// </param>
        /// <param name="pnpDriverInf"></param>
        private void ProcessAddRegSection(PNPDriverINFFile pnpDriverInf, string sectionName, string relativeRoot)
        {
            var section = pnpDriverInf.GetSection(sectionName);

            foreach (var line in section)
            {
                var values     = INIFile.GetCommaSeparatedValues(line);
                var hiveName   = values[0];
                var subKeyName = INIFile.Unquote(values[1]);
                var valueName  = INIFile.TryGetValue(values, 2);
                var valueType  = INIFile.TryGetValue(values, 3);

                var valueDataUnparsed = string.Empty;
                if (values.Count > 3)
                {
                    valueDataUnparsed = StringUtils.Join(values.GetRange(4, values.Count - 4), ",");
                }
                // byte-list is separated using commmas

                valueName = INIFile.Unquote(valueName);
                valueType = pnpDriverInf.ExpandToken(valueType);
                var valueTypeFlags = PNPDriverINFFile.ConvertFromIntStringOrHexString(valueType);
                var valueKind      = PNPDriverINFFile.GetRegistryValueKind(valueTypeFlags);
                if (valueKind == RegistryValueKind.String)
                {
                    valueDataUnparsed = pnpDriverInf.ExpandToken(valueDataUnparsed);
                }
                var valueData = HiveINIFile.ParseValueDataString(valueDataUnparsed, valueKind);

                if (hiveName == "HKR")
                {
                    var cssKeyName = relativeRoot;
                    if (subKeyName != string.Empty)
                    {
                        cssKeyName = cssKeyName + @"\" + subKeyName;
                    }
                    // Note that software key will stick from text-mode:
                    SetCurrentControlSetRegistryKey(cssKeyName, valueName, valueKind, valueData);
                }
                else if (hiveName == "HKLM" &&
                         subKeyName.StartsWith(@"SYSTEM\CurrentControlSet\", StringComparison.InvariantCultureIgnoreCase))
                {
                    var cssKeyName = subKeyName.Substring(@"SYSTEM\CurrentControlSet\".Length);

                    SetCurrentControlSetRegistryKey(cssKeyName, valueName, valueKind, valueData);
                }
            }
        }
        private void ProcessCopyFilesSection(PNPDriverINFFile pnpDriverInf, string sectionName)
        {
            var section = pnpDriverInf.GetSection(sectionName);

            foreach (var line in section)
            {
                var values = INIFile.GetCommaSeparatedValues(line);
                var destinationFileName = values[0];
                var sourceFileName      = INIFile.TryGetValue(values, 1);
                if (sourceFileName == string.Empty)
                {
                    sourceFileName = destinationFileName;
                }
                ProcessCopyFileDirective(pnpDriverInf, sourceFileName, destinationFileName);
            }
        }
Esempio n. 7
0
        protected string GetRegistryValueData(string hive, string keyName, string valueName)
        {
            var    lineStart = string.Format("{0},\"{1}\",\"{2}\"", hive, keyName, valueName);
            string line;
            var    lineIndex = GetLineStartIndex("AddReg", lineStart, out line);

            if (lineIndex >= 0)
            {
                var valueDataStartIndex     = line.Substring(lineStart.Length + 1).IndexOf(",", StringComparison.Ordinal) + lineStart.Length + 2;
                var hexStringValueTypeFlags = line.Substring(lineStart.Length + 1, valueDataStartIndex - lineStart.Length - 2);
                var valueData = line.Substring(valueDataStartIndex);
                var valueKind = PNPDriverINFFile.GetRegistryValueKind(hexStringValueTypeFlags);
                return(valueKind == RegistryValueKind.MultiString
                                        ? valueData
                                        : Unquote(valueData));
            }

            return(string.Empty);
        }
        // http://msdn.microsoft.com/en-us/library/ff547478%28v=vs.85%29.aspx
        /// <returns>In the following form: 'WinNT\x86\'</returns>
        public static string GetRelativeDirectoryPath(PNPDriverINFFile pnpDriverInf, string sourceFileName, string architectureIdentifier)
        {
            string subdir;
            var    diskID = GeSourceFileDiskID(pnpDriverInf, sourceFileName, architectureIdentifier, out subdir);

            if (diskID == string.Empty)
            {
                // file location can come from either [SourceDisksFiles] section for vendor-provided drivers
                // or from layout.inf for Microsoft-provided drivers.
                // if there is no [SourceDisksFiles] section, we assume the user used a Microsoft-provided driver
                // and put all the necessary files in the root driver directory (where the .inf is located)
                //
                // Note: if [SourceDisksFiles] is not present, Windows GUI-mode setup will look for the files in the root driver directory as well.
                return(string.Empty);
            }

            if (subdir.StartsWith(@"\"))
            {
                subdir = subdir.Substring(1);
            }

            var relativePathToDisk = GeSourceDiskPath(pnpDriverInf, diskID, architectureIdentifier);

            if (relativePathToDisk == null)
            {
                Console.WriteLine("Warning: Could not locate DiskID '{0}'", diskID);
                return(string.Empty);                // Which means that the file is in the driver directory
            }
            if (relativePathToDisk == string.Empty)
            {
                // No path, which means that the disk root is the driver directory
                return(subdir + @"\");
            }
            if (relativePathToDisk.StartsWith(@"\"))
            {
                // We remove the leading backslash, and return the relative directory name + subdir
                return(relativePathToDisk.Substring(1) + @"\" + subdir + @"\");
            }
            Console.WriteLine("Warning: Invalid entry for DiskID '{0}'", diskID);
            return(subdir + @"\");
        }
        private void ProcessEventLogInstallSection(PNPDriverINFFile pnpDriverInf, string sectionName, string eventLogType,
                                                   string eventName)
        {
            var installSection = pnpDriverInf.GetSection(sectionName);

            var relativeRoot = @"Services\EventLog\" + eventLogType + @"\" + eventName;

            foreach (var line in installSection)
            {
                var keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "AddReg":
                {
                    foreach (var registrySectionName in keyAndValues.Value)
                    {
                        ProcessAddRegSection(pnpDriverInf, registrySectionName, relativeRoot);
                    }
                    break;
                }
                }
            }
        }
        protected void ProcessInstallServicesSection(PNPDriverINFFile pnpDriverInf, string installSectionName)
        {
            var installServicesSection = pnpDriverInf.GetInstallServicesSection(installSectionName, _architectureIdentifier,
                                                                                _minorOSVersion);

            foreach (var line in installServicesSection)
            {
                var keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "AddService":
                {
                    var serviceName            = keyAndValues.Value[0];
                    var serviceInstallSection  = keyAndValues.Value[2];
                    var eventLogInstallSection = INIFile.TryGetValue(keyAndValues.Value, 3);
                    var eventLogType           = INIFile.TryGetValue(keyAndValues.Value, 4);
                    var eventName = INIFile.TryGetValue(keyAndValues.Value, 5);
                    ProcessServiceInstallSection(pnpDriverInf, serviceInstallSection, serviceName);
                    if (eventLogInstallSection != string.Empty)
                    {
                        // http://msdn.microsoft.com/en-us/library/ff546326%28v=vs.85%29.aspx
                        if (eventLogType == string.Empty)
                        {
                            eventLogType = "System";
                        }
                        if (eventName == string.Empty)
                        {
                            eventName = serviceName;
                        }
                        ProcessEventLogInstallSection(pnpDriverInf, eventLogInstallSection, eventLogType, eventName);
                    }
                    break;
                }
                }
            }
        }
Esempio n. 11
0
        private void RegisterDeviceService(ISystemRegistryHive systemRegistryHive, PNPDriverINFFile pnpDriverInf, BaseDeviceService deviceService)
        {
            // We ignore start type. if the user uses this program, she wants to boot something!
            const int startType = 0;
            // Note: using a different service registry key under CurrentControlSet\Services with an ImagePath entry referring to the .sys will not work in text mode setup!
            // Text-mode setup will always initialize services based on the values stored under Services\serviceName, where serviceName is the service file name without the .sys extension.

            // write all to registry:
            var serviceName = deviceService.ServiceName;

            if (deviceService.ServiceDisplayName != string.Empty)
            {
                systemRegistryHive.SetServiceRegistryKey(
                    serviceName,
                    string.Empty,
                    "DisplayName",
                    RegistryValueKind.String,
                    deviceService.ServiceDisplayName);
            }
            systemRegistryHive.SetServiceRegistryKey(serviceName, string.Empty, "ErrorControl", RegistryValueKind.DWord, deviceService.ErrorControl);
            if (deviceService.ServiceGroup != string.Empty)
            {
                systemRegistryHive.SetServiceRegistryKey(
                    serviceName,
                    string.Empty,
                    "Group",
                    RegistryValueKind.String,
                    deviceService.ServiceGroup);
            }
            systemRegistryHive.SetServiceRegistryKey(serviceName, string.Empty, "Start", RegistryValueKind.DWord, startType);
            systemRegistryHive.SetServiceRegistryKey(serviceName, string.Empty, "Type", RegistryValueKind.DWord, deviceService.ServiceType);

            if (systemRegistryHive is HiveSystemINFFile)             // GUI Mode registry
            {
                systemRegistryHive.SetServiceRegistryKey(
                    serviceName,
                    string.Empty,
                    "ImagePath",
                    RegistryValueKind.String,
                    deviceService.ImagePath);
            }

            // Note that software key will stick from text-mode:
            var softwareKeyName = @"Control\Class\" + pnpDriverInf.ClassGUID + @"\" + _classInstanceID;

            var service = deviceService as NetworkDeviceService;

            if (service != null)
            {
                var netCfgInstanceID = service.NetCfgInstanceID;
                // - sanbootconf and iScsiBP use this value, but it's not necessary for successful boot, static IP can be used instead.
                // - the presence of this value will stick and stay for the GUI mode
                // - the presence of this value during GUI Mode will prevent the IP settings from being resetted
                // - the presence of this value will cause Windows 2000 \ XP x86 to hang after the NIC driver installation (there is no problem with Windows Server 2003)
                // - the presence of this value will cause Windows XP x64 to hang during the "Installing Network" phase (there is no problem with Windows Server 2003)

                // we will set this value so sanbootconf / iScsiBP could use it, and if necessary, delete it before the NIC driver installation (using hal.inf)
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "NetCfgInstanceId", RegistryValueKind.String, netCfgInstanceID);
                if (!_installation.IsWindowsServer2003)
                {
                    // delete the NetCfgInstanceId registry value during the beginning of GUI-mode setup
                    _installation.HalInf.DeleteNetCfgInstanceIdFromNetworkAdapterClassInstance(_classInstanceID);
                }

                // The Linkage subkey is critical, and is used to bind the network adapter to TCP/IP:
                // - The NetCfgInstanceId here is the one Windows actually uses for TCP/IP configuration.
                // - The first component in one entry corresponds to the first component in the other entries:
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "Linkage", "Export", RegistryValueKind.MultiString, new[] { @"\Device\" + netCfgInstanceID });
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "Linkage", "RootDevice", RegistryValueKind.MultiString, new[] { netCfgInstanceID });                 // Windows can still provide TCP/IP without this entry
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "Linkage", "UpperBind", RegistryValueKind.MultiString, new[] { "Tcpip" });
            }

            // We need to make sure the software key is created, otherwise two devices can end up using the same software key

            // Note for network adapters:
            // "MatchingDeviceId" is not critical for successfull boot or devices which are not network adapters, but it's critical for NICBootConf in case it's being used
            // Note: Windows will store the hardwareID as it appears in the driver, including &REV
            systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "MatchingDeviceId", RegistryValueKind.String, HardwareID.ToLower());

            // not necessary. in addition, it will also be performed by GUI-mode setup
            if (deviceService.DeviceDescription != string.Empty)
            {
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "DriverDesc", RegistryValueKind.String,
                                                                   deviceService.DeviceDescription);
            }
            if (pnpDriverInf.DriverVersion != string.Empty)
            {
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "DriverVersion", RegistryValueKind.String,
                                                                   pnpDriverInf.DriverVersion);
            }
            if (pnpDriverInf.Provider != string.Empty)
            {
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "ProviderName", RegistryValueKind.String,
                                                                   pnpDriverInf.Provider);
            }
        }
 private void ProcessCopyFileDirective(PNPDriverINFFile pnpDriverInf, string sourceFileName)
 {
     ProcessCopyFileDirective(pnpDriverInf, sourceFileName, sourceFileName);
 }
Esempio n. 13
0
        public void IntegrateDriver()
        {
            PNPDriverINFFile pnpDriverInf;
            var installSectionName = DriverDirectory.GetDeviceInstallSectionName(HardwareID, _installation.ArchitectureIdentifier, _installation.MinorOSVersion, _installation.ProductType, out pnpDriverInf);

            if (installSectionName == string.Empty)
            {
                Console.WriteLine("Unable to locate InstallSectionName in INF file");
                Program.Exit();
            }

            _classInstanceID = _installation.SetupRegistryHive.AllocateClassInstanceID(pnpDriverInf.ClassGUID);

            ProcessInstallSection(pnpDriverInf, installSectionName, _classInstanceID);
            ProcessInstallServicesSection(pnpDriverInf, installSectionName);
            // this.DeviceServices is now populated

            if (DeviceServices.Count == 0)
            {
                Console.WriteLine("Error: driver does not have an associated service, IntegrateDrv will not proceed.");
                Program.Exit();
            }

            PrepareToPreventTextModeDriverNameCollision(DeviceServices);

            foreach (var deviceService in DeviceServices)
            {
                InstructToLoadTextModeDeviceService(deviceService);
                RegisterDeviceService(_installation.SetupRegistryHive, pnpDriverInf, deviceService);
                RegisterDeviceService(_installation.HiveSystemInf, pnpDriverInf, deviceService);
            }

            CopyDriverFiles(DeviceServices);

            // register the device:

            if (PNPDriverINFFile.IsRootDevice(HardwareID))
            {
                // installing virtual device: (this is critical for some services such as iScsiPrt)
                var virtualDeviceInstanceID = _installation.AllocateVirtualDeviceInstanceID(pnpDriverInf.ClassName);
                if (DeviceServices.Count > 0)
                {
                    var deviceService = DeviceServices[0];
                    PreconfigureDeviceInstance(pnpDriverInf, "Root", pnpDriverInf.ClassName.ToUpper(), virtualDeviceInstanceID, deviceService);
                }
            }
            else             // physical device
            {
                RegisterPhysicalDevice(pnpDriverInf);

                // GUI-Mode setup will scan all of the directories listed under "DevicePath" directories,
                // if it will find multiple matches, it will use the .inf file that has the best match.
                // Microsoft does not define exactly how matching drivers are ranked, observations show that:
                // 1. When both .inf have the exact same hardwareID, and one of the .inf is signed and the other is not, the signed .inf will qualify as the best match.
                // 2. When both .inf have the exact same hardwareID, and both of the .inf files are unsigned, the .inf with the most recent version / date will qualify as the best match.
                // 3. When both .inf have the exact same hardwareID, and both of the .inf files are unsigned, and both has the same version / date, the .inf from the first directory listed under "DevicePath" will qualify as the best match.

                // We have to disable the device drivers included in windows to qualify the newly integrated drivers as best match:
                PNPDriverGUIModeIntegrator.DisableInBoxDeviceDrivers(_installation.SetupDirectory, _installation.ArchitectureIdentifier, _installation.MinorOSVersion, _installation.ProductType, HardwareID);
            }

            // Network Device:
            // We want to make the NIC driver accessible to windows GUI mode setup, otherwise no 'Network Connection' will be installed and TCP/IP configuration
            // for the NIC will be deleted. (and as a result, the NIC would not have TCP/IP bound to it)

            // Devices in general:
            // Windows will clear all existing Enum and / or Control\Class entries of devices that have no matching driver available during GUI-mode setup
            // (it will be done near the very end of GUI-mode setup)
            // So we let Windows GUI-Mode install the device.

            // Note: the driver will be modified for boot start
            var guiModeIntegrator = new PNPDriverGUIModeIntegrator(DriverDirectory, _installation, HardwareID);

            guiModeIntegrator.Integrate();
        }
Esempio n. 14
0
        // unlike other types of hardware (SCSI controllers etc.), it's not enough to add a NIC to the
        // Criticla Device Database (CDDB) to make it usable during boot (Note that NIC driver is an NDIS
        // miniport driver, and the driver does not have an AddDevice() routine and instead uses NDIS' AddDevice())
        // This method performs the additional steps needed for a NIC that is added to the CDDB, which are basically letting Windows
        // know which device class instance is related to the device (TCP/IP settings are tied to the device class instance)
        // The above is true for both text-mode and GUI-mode / Final Windows.
        // Note: it's best to use a driver that does these steps during boot, I have written NICBootConf for that purpose.

        /*
         * private void PreconfigureCriticalNetworkAdapter(PNPDriverINFFile pnpDriverInf, string enumerator, string deviceID, string deviceInstanceID, DeviceService deviceService)
         * {
         *      string keyName = @"ControlSet001\Enum\" + enumerator + @"\" + deviceID + @"\" + deviceInstanceID;
         *      m_installation.SetupRegistryHive.SetRegistryKey(keyName, "Driver", RegistryValueKind.String, pnpDriverInf.ClassGUID + @"\" + m_classInstanceID);
         *      // The presence of DeviceDesc is critical for some reason, but any value can be used
         *      m_installation.SetupRegistryHive.SetRegistryKey(keyName, "DeviceDesc", RegistryValueKind.String, deviceService.DeviceDescription);
         *
         *      // not critical:
         *      m_installation.SetupRegistryHive.SetRegistryKey(keyName, "ClassGUID", RegistryValueKind.String, pnpDriverInf.ClassGUID);
         *
         *      // we must not specify ServiceName or otherwise kernel-PNP will skip this device
         *
         *      // let kernel-PNP take care of the rest for us, ClassGUID is not critical:
         *      m_installation.TextSetupInf.AddDeviceToCriticalDeviceDatabase(this.HardwareID, deviceService.ServiceName);
         * }
         */

        /// <summary>
        /// When using this method, there is no need to use the Critical Device Database
        /// </summary>
        private void PreconfigureDeviceInstance(PNPDriverINFFile pnpDriverInf, string enumerator, string deviceID, string deviceInstanceID, BaseDeviceService deviceService)
        {
            PreconfigureDeviceInstance(pnpDriverInf, _installation.SetupRegistryHive, enumerator, deviceID, deviceInstanceID, deviceService);
            // Apparently this is not necessary for the devices to work properly in GUI-mode, because configuration will stick from text-mode setup:
            PreconfigureDeviceInstance(pnpDriverInf, _installation.HiveSystemInf, enumerator, deviceID, deviceInstanceID, deviceService);
        }
Esempio n. 15
0
        private void RegisterPhysicalDevice(PNPDriverINFFile pnpDriverInf)
        {
            if (_preconfigure && pnpDriverInf.IsNetworkAdapter && (_useLocalHardwareConfig || _enumExportPath != string.Empty))
            {
                string deviceID;
                string deviceInstanceID;

                if (_useLocalHardwareConfig)
                {
                    deviceInstanceID = PNPLocalHardwareDetector.DetectLocalDeviceInstanceID(HardwareID, out deviceID);
                    if (deviceInstanceID == string.Empty)
                    {
                        Console.WriteLine(
                            "Warning: Could not detect matching device installed locally, configuration will not be applied!");
                    }
                }
                else                 // m_enumExportPath != string.Empty
                {
                    deviceInstanceID = PNPExportedHardwareDetector.DetectExportedDeviceInstanceID(_enumExportPath, HardwareID, out deviceID);
                    if (deviceInstanceID == string.Empty)
                    {
                        Console.WriteLine(
                            "Warning: Could not detect matching device in the exported registry, configuration will not be applied!");
                    }
                }

                if (deviceInstanceID != string.Empty)
                {
                    // m_netDeviceServices is now populated
                    if (NetworkDeviceServices.Count > 0)
                    {
                        // unlike other types of hardware (SCSI controllers etc.), it's not enough to add a NIC to the
                        // Criticla Device Database (CDDB) to make it usable during boot, as mentioned in the comments above RegisterNicAsCriticalDevice()
                        // at the very least, a CDDB entry and a "Device" registry value under Enum\Enumerator\DeviceID\DeviceInstanceID is required
                        // (as well as DeviceDesc if not automatically added by the kernel-PNP)
                        // here we manually register the hardware in advance, but it's better to use NICBootConf to do this during boot,
                        // NICBootConf will also work if the NIC has been moved to another PCI slot since creating the installation media.

                        // the first item in m_netDeviceServices should be the actual NIC (CHECKME: what about NIC / bus driver combination like nVIdia)
                        var deviceService = NetworkDeviceServices[0];
                        var enumerator    = PNPDriverIntegratorUtils.GetEnumeratorNameFromHardwareID(HardwareID);
                        PreconfigureDeviceInstance(pnpDriverInf, enumerator, deviceID, deviceInstanceID, deviceService);
                    }
                    else
                    {
                        Console.WriteLine(
                            "Warning: failed to install '{0}', because the service for this network adapter has not been registered!",
                            HardwareID);
                    }
                }
            }
            else
            {
                // if it's a NIC, We assume the user will integrate NICBootConf, which will configure the network adapter during boot.
                // we'll just add the device to the Criticla Device Database (CDDB), and let kernel-PNP and NICBootConf do the rest.
                if (pnpDriverInf.IsNetworkAdapter)
                {
                    // NICBootConf needs the ClassGUID in place for each DeviceInstance Key,
                    // if we put the ClassGUID in the CDDB, the ClassGUID will be applied to each DeviceInstance with matching hardwareID
                    _installation.TextSetupInf.AddDeviceToCriticalDeviceDatabase(HardwareID, DeviceServices[0].ServiceName, PNPDriverINFFile.NetworkAdapterClassGUID);
                    _installation.HiveSystemInf.AddDeviceToCriticalDeviceDatabase(HardwareID, DeviceServices[0].ServiceName, PNPDriverINFFile.NetworkAdapterClassGUID);
                }
                else
                {
                    _installation.TextSetupInf.AddDeviceToCriticalDeviceDatabase(HardwareID, DeviceServices[0].ServiceName);
                    _installation.HiveSystemInf.AddDeviceToCriticalDeviceDatabase(HardwareID, DeviceServices[0].ServiceName);
                }
            }
        }
        private void ProcessServiceInstallSection(PNPDriverINFFile pnpDriverInf, string sectionName, string serviceName)
        {
            Console.WriteLine("Registering service '" + serviceName + "'");
            var serviceInstallSection = pnpDriverInf.GetSection(sectionName);

            var displayName        = string.Empty;
            var serviceBinary      = string.Empty;
            var serviceTypeString  = string.Empty;
            var errorControlString = string.Empty;
            var loadOrderGroup     = string.Empty;

            //string guiModeRelativeRoot = @"Services\" + serviceName;
            foreach (var line in serviceInstallSection)
            {
                var keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "AddReg":
                {
                    // http://msdn.microsoft.com/en-us/library/ff546326%28v=vs.85%29.aspx
                    // AddReg will always come after ServiceBinaryServiceBinary

                    var relativeRoot = @"Services\" + serviceName;

                    foreach (var registrySectionName in keyAndValues.Value)
                    {
                        ProcessAddRegSection(pnpDriverInf, registrySectionName, relativeRoot);
                    }
                    break;
                }

                case "DisplayName":
                {
                    displayName = INIFile.TryGetValue(keyAndValues.Value, 0);
                    break;
                }

                case "ServiceBinary":
                {
                    serviceBinary = INIFile.TryGetValue(keyAndValues.Value, 0);
                    break;
                }

                case "ServiceType":
                {
                    serviceTypeString = INIFile.TryGetValue(keyAndValues.Value, 0);
                    break;
                }

                case "ErrorControl":
                {
                    errorControlString = INIFile.TryGetValue(keyAndValues.Value, 0);
                    break;
                }

                case "LoadOrderGroup":
                {
                    loadOrderGroup = INIFile.TryGetValue(keyAndValues.Value, 0);
                    break;
                }
                }
            }

            displayName = pnpDriverInf.ExpandToken(displayName);
            displayName = INIFile.Unquote(displayName);

            var fileName  = serviceBinary.Replace(@"%12%\", string.Empty);
            var imagePath = PNPDriverINFFile.ExpandDirID(serviceBinary);

            var serviceType  = PNPDriverINFFile.ConvertFromIntStringOrHexString(serviceTypeString);
            var errorControl = PNPDriverINFFile.ConvertFromIntStringOrHexString(errorControlString);

            var deviceDescription = pnpDriverInf.GetDeviceDescription(_hardwareID, _architectureIdentifier, _minorOSVersion,
                                                                      _productType);

            BaseDeviceService deviceService;

            if (pnpDriverInf.IsNetworkAdapter)
            {
                // this is a nic, we are binding TCP/IP to it
                // we need a unique NetCfgInstanceID that will be used with Tcpip service and the nic's class
                var netCfgInstanceID = "{" + Guid.NewGuid().ToString().ToUpper() + "}";
                deviceService = new NetworkDeviceService(deviceDescription, serviceName, displayName, loadOrderGroup, serviceType,
                                                         errorControl, fileName, imagePath, netCfgInstanceID);
                _deviceServices.Add(deviceService);
            }
            else
            {
                deviceService = new BaseDeviceService(deviceDescription, serviceName, displayName, loadOrderGroup, serviceType,
                                                      errorControl, fileName, imagePath);
                _deviceServices.Add(deviceService);
            }
        }
        private void CopyDriverToSetupDriverDirectoryAndRegisterIt(PNPDriverINFFile pnpDriverInf)
        {
            Console.WriteLine();
            Console.WriteLine("Making the driver available to GUI mode setup.");

            // build list of source files:
            var driverFiles = new List <string>();

            foreach (var fileToCopy in DriverFilesToCopy)
            {
                DisableInBoxDeviceDriverFile(_installation.SetupDirectory, fileToCopy.DestinationFileName);

                driverFiles.Add(fileToCopy.RelativeSourceFilePath);
            }

            // make sure the .inf file will be copied too
            driverFiles.Add(pnpDriverInf.FileName);

            if (pnpDriverInf.CatalogFile != string.Empty)
            {
                if (File.Exists(DriverDirectory.Path + pnpDriverInf.CatalogFile))
                {
                    // add the catalog file too (to suppress unsigned driver warning message if the .inf has not been modified)
                    // the catalog file is in the same location as the INF file ( http://msdn.microsoft.com/en-us/library/windows/hardware/ff547502%28v=vs.85%29.aspx )
                    driverFiles.Add(pnpDriverInf.CatalogFile);
                }
            }

            // Note that we may perform some operations on the same directory more than once,
            // the allocate / register methods are supposed to return the previously allocated IDs on subsequent calls,
            // and skip registration of previously registered directories
            foreach (var relativeFilePath in driverFiles)
            {
                var fileName = FileSystemUtils.GetNameFromPath(relativeFilePath);
                var relativeDirectoryPath = relativeFilePath.Substring(0, relativeFilePath.Length - fileName.Length);

                // we need to copy the files to the proper sub-directories
                var sourceDir      = DriverDirectory.Path + relativeDirectoryPath;
                var pathParts      = sourceDir.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
                var destinationDir = pnpDriverInf.ClassName + '\\' + pathParts[pathParts.Length - 1] + relativeDirectoryPath + Path.DirectorySeparatorChar;
                _installation.CopyFileToSetupDriverDirectory(sourceDir + fileName, destinationDir, fileName);

                var sourceDirectoryInMediaRootForm = _installation.GetSourceDriverDirectoryInMediaRootForm(HardwareID + @"\" + relativeDirectoryPath);                 // note that we may violate ISO9660 - & is not allowed
                var sourceDiskID = _installation.TextSetupInf.AllocateSourceDiskID(_installation.ArchitectureIdentifier, sourceDirectoryInMediaRootForm);

                var destinationWinntDirectory   = _installation.GetDriverDestinationWinntDirectory(HardwareID + @"\" + relativeDirectoryPath);
                var destinationWinntDirectoryID = _installation.TextSetupInf.AllocateWinntDirectoryID(destinationWinntDirectory);

                _installation.TextSetupInf.SetSourceDisksFileEntry(_installation.ArchitectureIdentifier, sourceDiskID, destinationWinntDirectoryID, fileName, FileCopyDisposition.AlwaysCopy);

                // dosnet.inf: we add the file to the list of files to be copied to local source directory
                if (!_installation.IsTargetContainsTemporaryInstallation)
                {
                    _installation.DOSNetInf.InstructSetupToCopyFileFromSetupDirectoryToLocalSourceDriverDirectory(
                        sourceDirectoryInMediaRootForm, fileName);
                }

                _installation.HiveSoftwareInf.RegisterDriverDirectory(destinationWinntDirectory);
                if (_installation.Is64Bit)
                {
                    // hivsft32.inf
                    _installation.HiveSoftware32Inf.RegisterDriverDirectory(destinationWinntDirectory);
                }
            }

            // set inf to boot start:
            {
                var sourceDir      = DriverDirectory.Path;
                var pathParts      = sourceDir.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
                var destinationDir = pnpDriverInf.ClassName + '\\' + pathParts[pathParts.Length - 1];

                var setupDriverDirectoryPath = _installation.GetSetupDriverDirectoryPath(destinationDir + Path.DirectorySeparatorChar);
                var installSectionName       = pnpDriverInf.GetDeviceInstallSectionName(HardwareID, _installation.ArchitectureIdentifier, _installation.MinorOSVersion, _installation.ProductType);
                pnpDriverInf.SetServiceToBootStart(installSectionName, _installation.ArchitectureIdentifier, _installation.MinorOSVersion);
                pnpDriverInf.SaveToDirectory(setupDriverDirectoryPath);
                // finished setting inf to boot start
            }
        }
        // DDInstall Section in a Network INF File:
        // http://msdn.microsoft.com/en-us/library/ff546329%28VS.85%29.aspx
        protected void ProcessInstallSection(PNPDriverINFFile pnpDriverInf, string installSectionName, string classInstanceID)
        {
            var installSection = pnpDriverInf.GetInstallSection(installSectionName, _architectureIdentifier, _minorOSVersion);

            var softwareKeyName = @"Control\Class\" + pnpDriverInf.ClassGUID + @"\" + classInstanceID;

            foreach (var line in installSection)
            {
                var keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "AddReg":
                {
                    foreach (var registrySectionName in keyAndValues.Value)
                    {
                        ProcessAddRegSection(pnpDriverInf, registrySectionName, softwareKeyName);
                    }
                    break;
                }

                case "CopyFiles":
                {
                    if (keyAndValues.Value[0].StartsWith("@"))
                    {
                        ProcessCopyFileDirective(pnpDriverInf, keyAndValues.Value[0].Substring(1));
                    }
                    else
                    {
                        foreach (var copyFilesSectionName in keyAndValues.Value)
                        {
                            ProcessCopyFilesSection(pnpDriverInf, copyFilesSectionName);
                        }
                    }
                    break;
                }

                case "BusType":
                {
                    if (pnpDriverInf.IsNetworkAdapter)
                    {
                        // Some NICs (AMD PCNet) won't start if BusType is not set (CM_PROB_FAILED_START)
                        var busType = Convert.ToInt32(keyAndValues.Value[0]);

                        SetCurrentControlSetRegistryKey(softwareKeyName, "BusType", RegistryValueKind.String, busType.ToString(CultureInfo.InvariantCulture));
                    }
                    break;
                }

                case "Characteristics":
                {
                    if (pnpDriverInf.IsNetworkAdapter)
                    {
                        // No evidence so far that the presence of this value is critical, but it's a good practice to add it
                        var characteristics = PNPDriverINFFile.ConvertFromIntStringOrHexString(keyAndValues.Value[0]);

                        SetCurrentControlSetRegistryKey(softwareKeyName, "Characteristics", RegistryValueKind.DWord, characteristics);
                    }
                    break;
                }
                }
            }
        }