ManagedDism icon indicating copy to clipboard operation
ManagedDism copied to clipboard

FullPath in OriginalFileName and PublishedName shouldn't be used when comparing DismDriverPackage

Open elf2k00 opened this issue 1 year ago • 3 comments

The Equals override implementation for DismDriverPackage uses all the properties to compare a DismDriverPackage object with another, but even when they are equal they might have been already installed (and these properties changed) or its files be located in another folder.

public bool Equals(DismDriverPackage? other)
        {
            return other != null
                   && BootCritical == other.BootCritical
                   && InBox == other.InBox
                   && CatalogFile == other.CatalogFile
                   && ClassDescription == other.ClassDescription
                   && ClassGuid == other.ClassGuid
                   && ClassName == other.ClassName
                   && Date == other.Date
                   && DriverSignature == other.DriverSignature
                   && OriginalFileName == other.OriginalFileName
                   && ProviderName == other.ProviderName
                   && PublishedName == other.PublishedName;
        }

For example a comparison for the same driver vm3d.inf, one read from an offline DriverStore and the other read from the downloaded driver returns false when they are the same driver.

DriverStore:

Original Filename: G:\Windows\System32\DriverStore\FileRepository\vm3d.inf_amd64_9d22a6e67525b799\vm3d.inf Published Name: oem1.inf

Downloaded Driver:

Original Filename: C:\drivers\vmware3d\vm3d.inf Published Name: vm3d.inf

Filename and not the Full Path should be used for comparing OriginalFilename, and PublishedName shouldn't be used at all because the .inf name changes when installed and might be different between installations.

elf2k00 avatar Feb 06 '24 14:02 elf2k00

Not trying to rehash the age-old domain-aware against domain-agnostic equals and hash-code debate, and I do not speak for @jeffkl, but my personal preference is the latter. The responsibility of Equals and GetHashCode should remain limited to ensuring ValueType equality between class instances. As an aside, I would go as far as changing the classes to records and rely on the compiler synthesized ValueType Equals and GetHashCode methods.

I do understand your problem though, and you could solve it using a dedicated Comparer, or an IsInstalled method, maybe as an extension for DismDriver(Package). Please be aware though, that DismGetDriverInfo may return different lists of DismDriver structures for the same DismDriverPackage, based on whether you call the method for a published (installed) driver or a local .inf file. See DismDriver for more information.

hdensity avatar Dec 04 '24 08:12 hdensity

I tend to agree, Equals() is just seeing if two objects are equal and in this case its correct. I'm interested to know about the scenario where you're comparing to DismDriverPackage instances? If needed, I'm all for adding a new method that compares these objects in a more specific way or adding a implementation of IComparer and adding an overload to Equals()

jeffkl avatar Dec 04 '24 16:12 jeffkl

I think what OP is looking for, is for driverPackageFromPublishedNameInstance == driverPackageFromInfFileInstance to be true, if the former originated, or was installed from, the latter. Or in other words a driverPackageFromInfFileInstance.IsAlreadyInstalled(), or something to that effect.

I think this could be achieved, but DriverPackageInfo alone is insufficient. At the very least, you'd also need to make sure that the installed drivers is a subset of drivers available in the inf file. Not too difficult, but requires access to the session:

public bool isAlreadyInstalled(DismSession session) {
  if (inbox) // Not sure about this one, might be true if pointing at an inf file under Windows\System32\drivers.
  {
    return true;
  }

  foreach(DriverPackageInfo driverPackageInfo in GetDrivers(session, false)) {
    if (this != driverPackageInfo, without PublishedName or OriginalFileName)
    {
      return false;
    }

    DismDriverCollection installedDrivers = GetDriverInfo(...);
    if (installedDrivers is subset of this.drivers)
    {
      return true;
    }
  }

  return false;
}

Lastly, other than maybe through the Inbox field, and as far as I can tell, Dism does not include information on whether a given DismDriver(Package)Info instance was returned for an installed driver package or not. While not an issue as such, it would be nice to have, so that the method above can avoid costly calls to DismApi.

hdensity avatar Dec 09 '24 20:12 hdensity