none
Issue with enumerating installed print drivers using SetupDiXXX functions RRS feed

  • Question

  • I am trying to enumerate all of the printer drivers that are installed locally on my system. These drivers are enumerated property using the command pnputil.exe - e The reason for wanting to enumerate is because there a multiple versions of the same printer driver in the driver store(%windows%\INF). When a user wants to add a printer driver using the Add Printer Driver wizard in Windows, he is presented with multiple versions of the same printer driver to select. This is confusing and not desirable. The multiple versions of driver files is seen in the "Add Printer Driver" wizard as there are multiple copies of the driver INF under %windows%\INF, with each INF corresponding to a different version of the same printer driver. So my goal is to enumerate all of the OEM*.inf files associated with a certain printer driver, and then delete these OEM*.inf files from the Driver store. To enumerate the OEM*.inf files, i am using the following piece of code:

    int _tmain(int argc, _TCHAR* argv[])
    {
        HDEVINFO Devs;
        SP_DEVINFO_DATA DevInfo;
        SP_DEVINSTALL_PARAMS deviceInstallParams;
            SP_DRVINFO_DATA DriverInfoData;
            SP_DRVINFO_DETAIL_DATA driverInfoDetail;
        BOOL rc = FALSE;
        DWORD index =0;
        BOOL match = FALSE;




        ZeroMemory(&DevInfo, sizeof(DevInfo));
        ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams));
            ZeroMemory(&DriverInfoData, sizeof(DriverInfoData));

        DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
            DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
        deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

    //SetupDiClassGuidsFromName(_T("Printers"), &cls, 1, &numClass);

    //  Devs = SetupDiGetClassDevs(&GUID_DEVCLASS_PRINTER,NULL,NULL,DIGCF_PRESENT); 
    //The above does not work. Returns no devices. Hence, i use DIGCF_ALLCLASSES in the following statement.
        Devs = SetupDiGetClassDevs(NULL,NULL,NULL,DIGCF_ALLCLASSES  );


        for(index=0; SetupDiEnumDeviceInfo(Devs, index, &DevInfo); index++) {

            if(!SetupDiGetDeviceInstallParams(Devs, &DevInfo, &deviceInstallParams)) {
                return FALSE;
            }

            deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER |  DI_FLAGSEX_ALLOWEXCLUDEDDRVS) ;


            if(!SetupDiSetDeviceInstallParams(Devs, &DevInfo, &deviceInstallParams)) {
                return FALSE;
            }

            if(!SetupDiBuildDriverInfoList(Devs, &DevInfo, SPDIT_CLASSDRIVER)) {
                return FALSE;
            }


                for(int c=0;SetupDiEnumDriverInfo(Devs,&DevInfo,SPDIT_CLASSDRIVER,c,&DriverInfoData);c++)
                {
                    _tprintf(_T("The name of the  Manufacturer is:%ws\n"),DriverInfoData.MfgName);
                    if((_tcscmp(DriverInfoData.MfgName,_T("Citrix"))==0)     &&(_tcscmp(DriverInfoData.ProviderName,_T("Citrix"))==0) || _tcscmp(DriverInfoData.ProviderName,_T("Citrix Systems"))==0) {
                    //
                    // these two fields match, try more detailed info
                    // to ensure we have the exact driver entry used
                    //
                    SP_DRVINFO_DETAIL_DATA detail;
                    detail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
                    if(!SetupDiGetDriverInfoDetail(Devs,&DevInfo,&DriverInfoData,&detail,sizeof(detail),NULL)   && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
                        continue;
                    }
                    _tprintf(_T("The name of the  oem file is:%ws\n"),detail.InfFileName);
                    if((_tcscmp(detail.SectionName,_T("CitrixEMFDrv"))==0)) {
                        _tprintf(_T("The name of the matching oem file is:%ws\n"),detail.InfFileName);
                        match = TRUE;
                        break;
                    }


            }
            SetupDiDestroyDriverInfoList(Devs,&DevInfo,DIGCF_ALLCLASSES);


        }


    if (Devs) {
        SetupDiDestroyDeviceInfoList(Devs);
        } 

    return 0;

    }

    Here are the issues with the above piece of code: -Firstly, i am unable to filter the printer class drivers using Devs = SetupDiGetClassDevs(&GUID_DEVCLASS_PRINTER,NULL,NULL,DIGCF_PRESENT) . No printer drivers are enumerated.I am unable to understand as to what is wrong here. The only way to have some drivers enumerated is to make use of DIGCF_ALLCLASSES. However, still, none of my printer drivers are enumerated. Only few of the drivers installed on the system are enumerated.

    All that i want to achieve is to enumerate all of the printer drivers installed on the system.

    -In the SP_DEVINSTALL_PARAMS structure, when i set the value of deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS ; In this case, all of the drivers on the system are enumerated. The problem i am seeing here is that the drivers are enumerated multiple times. Furthermore, the enumeration takes some decent amount of time and is resulting in time lag. When i set the value of deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS ); some drivers on the system are enumerated. However, the printer drivers are not.

    -What technique does pnputil -e use to enumerate all of the drivers installed on the system.

    Any response would be very much appreciated.

    Thanks,


    Thursday, January 9, 2014 4:55 AM

All replies

  • if you notice in device manager there are no pnp printers listed.  SetupDi functions work on pnp driver packages and printer driver packages are not that.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, January 9, 2014 6:59 AM
  • Thanks for responding back.

    In the SP_DEVINSTALL_PARAMS structure, when i set the value of deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS ; In this case, all of the drivers on the system are enumerated. The problem i am seeing here is that the drivers are enumerated multiple times. Furthermore, the enumeration takes some decent amount of time and is resulting in time lag. 

    So what does pnputil -e use to list the drivers installed on the system?

    Do you know of a way if i could acheive something similar?

    Thanks,




    Friday, January 10, 2014 6:15 AM
  • Hello there,

    Any comments?

    Thanks

    Friday, January 17, 2014 5:18 AM