예제 #1
0
        protected void ProcessCoInstallersSection(PNPDriverINFFile pnpDriverInf, string installSectionName)
        {
            string matchingInstallSectionName = pnpDriverInf.GetMatchingInstallSectionName(installSectionName, m_architectureIdentifier, m_minorOSVersion);

            if (matchingInstallSectionName == String.Empty)
            {
                return;
            }
            string        matchingCoInstallersSectionName = matchingInstallSectionName + ".CoInstallers";
            List <string> coinstallersSection             = pnpDriverInf.GetSection(matchingCoInstallersSectionName);

            foreach (string line in coinstallersSection)
            {
                KeyValuePair <string, List <string> > keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "CopyFiles":
                    if (keyAndValues.Value[0].StartsWith("@"))
                    {
                        ProcessCopyFileDirective(pnpDriverInf, keyAndValues.Value[0].Substring(1));
                    }
                    else
                    {
                        foreach (string copyFilesSectionName in keyAndValues.Value)
                        {
                            ProcessCopyFilesSection(pnpDriverInf, copyFilesSectionName);
                        }
                    }
                    break;

                default:
                    break;
                }
            }
        }
예제 #2
0
        private void PreconfigureDeviceInstance(PNPDriverINFFile pnpDriverInf, ISystemRegistryHive systemRegistryHive, string enumerator, string deviceID, string deviceInstanceID, DeviceService deviceService)
        {
            string driver           = pnpDriverInf.ClassGUID.ToUpper() + @"\" + m_classInstanceID;
            string manufacturerName = pnpDriverInf.GetDeviceManufacturerName(this.HardwareID, m_installation.ArchitectureIdentifier, m_installation.MinorOSVersion, m_installation.ProductType);

            string 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(this.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 string[] { this.HardwareID });
            }

            // not necessary:
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "Mfg", RegistryValueKind.String, manufacturerName);
            systemRegistryHive.SetCurrentControlSetRegistryKey(hardwareKeyName, "Class", RegistryValueKind.String, pnpDriverInf.ClassName);
        }
예제 #3
0
        protected string GetRegistryValueData(string hive, string keyName, string valueName)
        {
            string lineStart = String.Format("{0},\"{1}\",\"{2}\"", hive, keyName, valueName);
            string line;
            int    lineIndex = GetLineStartIndex("AddReg", lineStart, out line);

            if (lineIndex >= 0)
            {
                int               valueDataStartIndex     = line.Substring(lineStart.Length + 1).IndexOf(",") + lineStart.Length + 2;
                string            hexStringValueTypeFlags = line.Substring(lineStart.Length + 1, valueDataStartIndex - lineStart.Length - 2);
                string            valueData = line.Substring(valueDataStartIndex);
                RegistryValueKind valueKind = PNPDriverINFFile.GetRegistryValueKind(hexStringValueTypeFlags);
                if (valueKind == RegistryValueKind.MultiString)
                {
                    return(valueData);
                }
                else
                {
                    return(Unquote(valueData));
                }
            }
            else
            {
                return(String.Empty);
            }
        }
예제 #4
0
        /// <param name="relativeRoot">
        /// The location where HKR entried will be stored, relative to 'SYSTEM\CurrentControlSet\' (or ControlSet001 for that matter)
        /// </param>
        private void ProcessAddRegSection(PNPDriverINFFile pnpDriverInf, string sectionName, string relativeRoot)
        {
            List <string> section = pnpDriverInf.GetSection(sectionName);

            foreach (string line in section)
            {
                List <string> values            = INIFile.GetCommaSeparatedValues(line);
                string        hiveName          = values[0];
                string        subKeyName        = INIFile.Unquote(values[1]);
                string        valueName         = INIFile.TryGetValue(values, 2);
                string        valueType         = INIFile.TryGetValue(values, 3);;
                string        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);
                int    valueTypeFlags = PNPDriverINFFile.ConvertFromIntStringOrHexString(valueType);
                string valueTypeHexString;
                if (!valueType.StartsWith("0x"))
                {
                    valueTypeHexString = "0x" + valueTypeFlags.ToString("X8"); // we want value type in 8 digit hex string.
                }
                else
                {
                    valueTypeHexString = valueType;
                }
                RegistryValueKind valueKind = PNPDriverINFFile.GetRegistryValueKind(valueTypeFlags);
                if (valueKind == RegistryValueKind.String)
                {
                    valueDataUnparsed = pnpDriverInf.ExpandToken(valueDataUnparsed);
                }
                object valueData = HiveINIFile.ParseValueDataString(valueDataUnparsed, valueKind);

                if (hiveName == "HKR")
                {
                    string 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))
                {
                    string cssKeyName = subKeyName.Substring(@"SYSTEM\CurrentControlSet\".Length);

                    SetCurrentControlSetRegistryKey(cssKeyName, valueName, valueKind, valueData);
                }
                else
                {
                    //Console.WriteLine("Warning: unsupported registry path: " + hiveName + @"\" + subKeyName);
                }
            }
        }
예제 #5
0
        // 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)
        {
            List <string> installSection = pnpDriverInf.GetInstallSection(installSectionName, m_architectureIdentifier, m_minorOSVersion);

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

            foreach (string line in installSection)
            {
                KeyValuePair <string, List <string> > keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "AddReg":
                    foreach (string 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 (string 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)
                        int busType = Convert.ToInt32(keyAndValues.Value[0]);

                        SetCurrentControlSetRegistryKey(softwareKeyName, "BusType", RegistryValueKind.String, busType.ToString());
                    }
                    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
                        int characteristics = PNPDriverINFFile.ConvertFromIntStringOrHexString(keyAndValues.Value[0]);

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

                default:
                    break;
                }
            }
        }
예제 #6
0
        // 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):");
            string[] filePaths = Directory.GetFiles(setupDirectory, "*.in_");
            foreach (string filePath in filePaths)
            {
                string packedFileName   = FileSystemUtils.GetNameFromPath(filePath);
                string unpackedFileName = packedFileName.Substring(0, packedFileName.Length - 1) + "F"; // the filename inside the archive ends with .INF and not with .IN_

                CabInfo 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)
                {
                    PNPDriverINFFile 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
                    bool 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.");
        }
예제 #7
0
        private void ProcessCopyFileDirective(PNPDriverINFFile pnpDriverInf, string sourceFileName, string destinationFileName)
        {
            string     relativeSourcePath = PNPDriverIntegratorUtils.GetRelativeDirectoryPath(pnpDriverInf, sourceFileName, m_architectureIdentifier);
            FileToCopy fileToCopy         = new FileToCopy(relativeSourcePath, sourceFileName, destinationFileName);

            if (!FileSystemUtils.IsFileExist(m_driverDirectory.Path + fileToCopy.RelativeSourceFilePath))
            {
                Console.WriteLine("Error: Missing file: " + m_driverDirectory.Path + fileToCopy.RelativeSourceFilePath);
                Program.Exit();
            }
            // actual copy will be performed later
            m_driverFilesToCopy.Add(fileToCopy);
        }
예제 #8
0
        List <KeyValuePair <string, string> > m_devices = null; // this include list of the devices from all the INFs in the directory

        public PNPDriverDirectory(string path)
        {
            m_path = path;

            List <string> fileNames = GetINFFileNamesInDirectory(path);

            m_infList = new List <PNPDriverINFFile>();
            foreach (string fileName in fileNames)
            {
                PNPDriverINFFile driverInf = new PNPDriverINFFile(fileName);
                driverInf.ReadFromDirectory(path);
                m_infList.Add(driverInf);
            }
        }
예제 #9
0
        /// <param name="subdir">Presumably in the following form: '\x86'</param>
        public static string GeSourceFileDiskID(PNPDriverINFFile pnpDriverInf, string sourceFileName, string architectureIdentifier, out string subdir)
        {
            // During installation, SetupAPI functions look for architecture-specific SourceDisksFiles sections before using the generic section
            string        platformSpecificSectionName = "SourceDisksFiles." + architectureIdentifier;
            List <string> values = pnpDriverInf.GetValuesOfKeyInSection(platformSpecificSectionName, sourceFileName);

            if (values.Count == 0)
            {
                values = pnpDriverInf.GetValuesOfKeyInSection("SourceDisksFiles", sourceFileName);
            }
            // filename=diskid[,[ subdir][,size]]
            string diskID = INIFile.TryGetValue(values, 0);

            subdir = INIFile.TryGetValue(values, 1);
            return(diskID);
        }
예제 #10
0
        private void ProcessCopyFilesSection(PNPDriverINFFile pnpDriverInf, string sectionName)
        {
            List <string> section = pnpDriverInf.GetSection(sectionName);

            foreach (string line in section)
            {
                List <string> values = INIFile.GetCommaSeparatedValues(line);
                string        destinationFileName = values[0];
                string        sourceFileName      = INIFile.TryGetValue(values, 1);
                if (sourceFileName == String.Empty)
                {
                    sourceFileName = destinationFileName;
                }
                ProcessCopyFileDirective(pnpDriverInf, sourceFileName, destinationFileName);
            }
        }
예제 #11
0
        // 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;
            string 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);
            }
            else
            {
                if (subdir.StartsWith(@"\"))
                {
                    subdir = subdir.Substring(1);
                }

                string 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
                }
                else if (relativePathToDisk == String.Empty)
                {
                    // No path, which means that the disk root is the driver directory
                    return(subdir + @"\");
                }
                else if (relativePathToDisk.StartsWith(@"\"))
                {
                    // We remove the leading backslash, and return the relative directory name + subdir
                    return(relativePathToDisk.Substring(1) + @"\" + subdir + @"\");
                }
                else
                {
                    Console.WriteLine("Warning: Invalid entry for DiskID '{0}'", diskID);
                    return(subdir + @"\");
                }
            }
        }
예제 #12
0
 private void InstructToLoadTextModeDeviceService(PNPDriverINFFile pnpDriverInf, DeviceService deviceService)
 {
     // update txtsetup.sif
     if (deviceService.ServiceGroup == String.Empty)
     {
         // No group, which means txtsetup.sif will have effect on initialization order.
         // In final Windows this means the service is initialized after all other services.
         // To do the same in text-mode, we should load this service last (which means using the [CdRomDrivers.Load] section):
         m_installation.TextSetupInf.InstructToLoadCdRomDriversDriver(deviceService.TextModeFileName, deviceService.DeviceDescription);
     }
     else
     {
         // we have set a group in setupreg.hiv, so for text-mode it doesn't matter where we put the service in txtsetup.sif,
         // however, some of the [xxxx.Load] groups will stick and cause problems later (GUI-mode / final Windows),
         // see TextSetupINFFile.Load.cs to see which groups may cause problems
         //
         // Note that the service is renamed back to its original name if necessary.
         m_installation.TextSetupInf.InstructToLoadKeyboardDriver(deviceService.TextModeFileName, deviceService.DeviceDescription);
     }
 }
예제 #13
0
        /// <returns>
        /// Null if the diskID entry was not found,
        /// otherwise, the path is supposed to be in the following form: '\WinNT'
        /// </returns>
        public static string GeSourceDiskPath(PNPDriverINFFile pnpDriverInf, string diskID, string architectureIdentifier)
        {
            List <string> values = pnpDriverInf.GetValuesOfKeyInSection("SourceDisksNames." + architectureIdentifier, diskID);

            if (values.Count == 0)
            {
                values = pnpDriverInf.GetValuesOfKeyInSection("SourceDisksNames", diskID);
            }

            if (values.Count > 0)
            {
                // diskid = disk-description[,[tag-or-cab-file],[unused],[path],[flags][,tag-file]]
                string path = INIFile.TryGetValue(values, 3);
                // Quoted path is allowed (example: SiS 900-Based PCI Fast Ethernet Adapter driver, version 2.0.1039.1190)
                return(QuotedStringUtils.Unquote(path));
            }
            else
            {
                return(null);
            }
        }
예제 #14
0
        private void ProcessEventLogInstallSection(PNPDriverINFFile pnpDriverInf, string sectionName, string eventLogType, string eventName)
        {
            List <string> installSection = pnpDriverInf.GetSection(sectionName);

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

            foreach (string line in installSection)
            {
                KeyValuePair <string, List <string> > keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "AddReg":
                    foreach (string registrySectionName in keyAndValues.Value)
                    {
                        ProcessAddRegSection(pnpDriverInf, registrySectionName, relativeRoot);
                    }
                    break;

                default:
                    break;
                }
            }
        }
예제 #15
0
        protected void ProcessInstallServicesSection(PNPDriverINFFile pnpDriverInf, string installSectionName)
        {
            List <string> installServicesSection = pnpDriverInf.GetInstallServicesSection(installSectionName, m_architectureIdentifier, m_minorOSVersion);

            foreach (string line in installServicesSection)
            {
                KeyValuePair <string, List <string> > keyAndValues = INIFile.GetKeyAndValues(line);
                switch (keyAndValues.Key)
                {
                case "AddService":
                    string serviceName            = keyAndValues.Value[0];
                    string serviceInstallSection  = keyAndValues.Value[2];
                    string eventLogInstallSection = INIFile.TryGetValue(keyAndValues.Value, 3);
                    string eventLogType           = INIFile.TryGetValue(keyAndValues.Value, 4);
                    string 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;

                default:
                    break;
                }
            }
        }
예제 #16
0
        public void CopyDriverToSetupDriverDirectoryAndRegisterIt(PNPDriverINFFile pnpDriverInf)
        {
            Console.WriteLine();
            Console.WriteLine("Making the driver available to GUI mode setup.");

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

            foreach (FileToCopy fileToCopy in this.DriverFilesToCopy)
            {
                DisableInBoxDeviceDriverFile(m_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(this.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 (string relativeFilePath in driverFiles)
            {
                string fileName = FileSystemUtils.GetNameFromPath(relativeFilePath);
                string relativeDirectoryPath = relativeFilePath.Substring(0, relativeFilePath.Length - fileName.Length);

                // we need to copy the files to the proper sub-directories
                m_installation.CopyFileToSetupDriverDirectory(this.DriverDirectory.Path + relativeDirectoryPath + fileName, this.HardwareID + @"\" + relativeDirectoryPath, fileName);

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

                string destinationWinntDirectory   = m_installation.GetDriverDestinationWinntDirectory(this.HardwareID + @"\" + relativeDirectoryPath);
                int    destinationWinntDirectoryID = m_installation.TextSetupInf.AllocateWinntDirectoryID(destinationWinntDirectory);

                m_installation.TextSetupInf.SetSourceDisksFileEntry(m_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 (!m_installation.IsTargetContainsTemporaryInstallation)
                {
                    m_installation.DosNetInf.InstructSetupToCopyFileFromSetupDirectoryToLocalSourceDriverDirectory(sourceDirectoryInMediaRootForm, fileName);
                }

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

            // set inf to boot start:
            string setupDriverDirectoryPath = m_installation.GetSetupDriverDirectoryPath(this.HardwareID + @"\"); // note that we may violate ISO9660 - & character is not allowed
            string installSectionName       = pnpDriverInf.GetDeviceInstallSectionName(this.HardwareID, m_installation.ArchitectureIdentifier, m_installation.MinorOSVersion, m_installation.ProductType);

            pnpDriverInf.SetServiceToBootStart(installSectionName, m_installation.ArchitectureIdentifier, m_installation.MinorOSVersion);
            pnpDriverInf.SaveToDirectory(setupDriverDirectoryPath);
            // finished setting inf to boot start
        }
예제 #17
0
        public static string GetRelativeSourceFilePath(PNPDriverINFFile pnpDriverInf, string sourceFileName, string architectureIdentifier)
        {
            string relativeDirectoryPath = GetRelativeDirectoryPath(pnpDriverInf, sourceFileName, architectureIdentifier);

            return(relativeDirectoryPath + sourceFileName);
        }
예제 #18
0
 private void ProcessCopyFileDirective(PNPDriverINFFile pnpDriverInf, string sourceFileName)
 {
     ProcessCopyFileDirective(pnpDriverInf, sourceFileName, sourceFileName);
 }
예제 #19
0
        private void ProcessServiceInstallSection(PNPDriverINFFile pnpDriverInf, string sectionName, string serviceName)
        {
            Console.WriteLine("Registering service '" + serviceName + "'");
            List <string> serviceInstallSection = pnpDriverInf.GetSection(sectionName);

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

            //string guiModeRelativeRoot = @"Services\" + serviceName;
            foreach (string line in serviceInstallSection)
            {
                KeyValuePair <string, List <string> > 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

                    string relativeRoot = @"Services\" + serviceName;

                    foreach (string 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;

                default:
                    break;
                }
            }

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

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

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

            string deviceDescription = pnpDriverInf.GetDeviceDescription(m_hardwareID, m_architectureIdentifier, m_minorOSVersion, m_productType);

            DeviceService 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
                string netCfgInstanceID = "{" + Guid.NewGuid().ToString().ToUpper() + "}";
                deviceService = new NetworkDeviceService(deviceDescription, serviceName, displayName, loadOrderGroup, serviceType, errorControl, fileName, imagePath, netCfgInstanceID);
                m_deviceServices.Add(deviceService);
            }
            else
            {
                deviceService = new DeviceService(deviceDescription, serviceName, displayName, loadOrderGroup, serviceType, errorControl, fileName, imagePath);
                m_deviceServices.Add(deviceService);
            }
        }
예제 #20
0
        private void RegisterDeviceService(ISystemRegistryHive systemRegistryHive, PNPDriverINFFile pnpDriverInf, DeviceService deviceService)
        {
            // We ignore start type. if the user uses this program, she wants to boot something!
            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:
            string 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:
            string softwareKeyName = @"Control\Class\" + pnpDriverInf.ClassGUID + @"\" + m_classInstanceID;

            if (deviceService is NetworkDeviceService)
            {
                string netCfgInstanceID = ((NetworkDeviceService)deviceService).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 (!m_installation.IsWindowsServer2003)
                {
                    // delete the NetCfgInstanceId registry value during the beginning of GUI-mode setup
                    m_installation.HalInf.DeleteNetCfgInstanceIdFromNetworkAdapterClassInstance(m_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 string[] { @"\Device\" + netCfgInstanceID });
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "Linkage", "RootDevice", RegistryValueKind.MultiString, new string[] { netCfgInstanceID }); // Windows can still provide TCP/IP without this entry
                systemRegistryHive.SetCurrentControlSetRegistryKey(softwareKeyName, "Linkage", "UpperBind", RegistryValueKind.MultiString, new string[] { "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, this.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);
            }
        }
예제 #21
0
        public void IntegrateDriver()
        {
            PNPDriverINFFile pnpDriverInf;
            string           installSectionName = this.DriverDirectory.GetDeviceInstallSectionName(this.HardwareID, m_installation.ArchitectureIdentifier, m_installation.MinorOSVersion, m_installation.ProductType, out pnpDriverInf);

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

            m_classInstanceID = m_installation.SetupRegistryHive.AllocateClassInstanceID(pnpDriverInf.ClassGUID);

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

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

            PrepareToPreventTextModeDriverNameCollision(this.DeviceServices);

            foreach (DeviceService deviceService in this.DeviceServices)
            {
                InstructToLoadTextModeDeviceService(pnpDriverInf, deviceService);
                RegisterDeviceService(m_installation.SetupRegistryHive, pnpDriverInf, deviceService);
                RegisterDeviceService(m_installation.HiveSystemInf, pnpDriverInf, deviceService);
            }

            CopyDriverFiles(this.DeviceServices);

            // register the device:

            if (PNPDriverINFFile.IsRootDevice(this.HardwareID))
            {
                // installing virtual device: (this is critical for some services such as iScsiPrt)
                string virtualDeviceInstanceID = m_installation.AllocateVirtualDeviceInstanceID(pnpDriverInf.ClassName);
                if (this.DeviceServices.Count > 0)
                {
                    DeviceService deviceService = this.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(m_installation.SetupDirectory, m_installation.ArchitectureIdentifier, m_installation.MinorOSVersion, m_installation.ProductType, this.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
            PNPDriverGUIModeIntegrator guiModeIntegrator = new PNPDriverGUIModeIntegrator(this.DriverDirectory, m_installation, this.HardwareID);

            guiModeIntegrator.Integrate();
        }
예제 #22
0
 public string GetDeviceInstallSectionName(string hardwareIDToFind, string architectureIdentifier, int minorOSVersion, int productType, out PNPDriverINFFile pnpDriverInf)
 {
     foreach (PNPDriverINFFile driverInf in m_infList)
     {
         string installSectionName = driverInf.GetDeviceInstallSectionName(hardwareIDToFind, architectureIdentifier, minorOSVersion, productType);
         if (installSectionName != String.Empty)
         {
             pnpDriverInf = driverInf;
             return(installSectionName);
         }
     }
     pnpDriverInf = null;
     return(String.Empty);
 }
예제 #23
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, DeviceService deviceService)
        {
            PreconfigureDeviceInstance(pnpDriverInf, m_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, m_installation.HiveSystemInf, enumerator, deviceID, deviceInstanceID, deviceService);
        }
예제 #24
0
        public void RegisterPhysicalDevice(PNPDriverINFFile pnpDriverInf)
        {
            if (m_preconfigure && pnpDriverInf.IsNetworkAdapter && (m_useLocalHardwareConfig || m_enumExportPath != String.Empty))
            {
                string deviceID;
                string deviceInstanceID;

                if (m_useLocalHardwareConfig)
                {
                    deviceInstanceID = PNPLocalHardwareDetector.DetectLocalDeviceInstanceID(this.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(m_enumExportPath, this.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 (this.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)
                        NetworkDeviceService deviceService = this.NetworkDeviceServices[0];
                        string enumerator = PNPDriverIntegratorUtils.GetEnumeratorNameFromHardwareID(this.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!", this.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
                    m_installation.TextSetupInf.AddDeviceToCriticalDeviceDatabase(this.HardwareID, this.DeviceServices[0].ServiceName, PNPDriverINFFile.NetworkAdapterClassGUID);
                    m_installation.HiveSystemInf.AddDeviceToCriticalDeviceDatabase(this.HardwareID, this.DeviceServices[0].ServiceName, PNPDriverINFFile.NetworkAdapterClassGUID);
                }
                else
                {
                    m_installation.TextSetupInf.AddDeviceToCriticalDeviceDatabase(this.HardwareID, this.DeviceServices[0].ServiceName);
                    m_installation.HiveSystemInf.AddDeviceToCriticalDeviceDatabase(this.HardwareID, this.DeviceServices[0].ServiceName);
                }
            }
        }