www.pudn.com > PCIConf.rar > Install.cpp


#include "stdafx.h" 
#include  // Make all functions UNICODE safe. 
#include  // for the API UpdateDriverForPlugAndPlayDevices(). 
#include  // for SetupDiXxx functions. 
#include "install.h" 
 
int DisplayError(TCHAR * ErrorName) 
{ 
    DWORD Err = GetLastError(); 
    LPVOID lpMessageBuffer = NULL; 
     
    if (FormatMessage(  
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 
        NULL,  
        Err,   
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
        (LPTSTR) &lpMessageBuffer,   
        0,   
        NULL )) 
        NULL;  //_tprintf(TEXT("%s FAILURE: %s\n"),ErrorName,(TCHAR *)lpMessageBuffer); 
    else  
        NULL;  //_tprintf(TEXT("%s FAILURE: (0x%08x)\n"),ErrorName,Err); 
     
    if (lpMessageBuffer) LocalFree( lpMessageBuffer ); // Free system buffer  
     
    SetLastError(Err);     
    return FALSE; 
} 
 
BOOL FindExistingDevice(IN LPTSTR HardwareId) 
{ 
    HDEVINFO DeviceInfoSet; 
    SP_DEVINFO_DATA DeviceInfoData; 
    DWORD i,err; 
    BOOL Found; 
     
    // 
    // Create a Device Information Set with all present devices. 
    // 
    DeviceInfoSet = SetupDiGetClassDevs(NULL, // All Classes 
        0, 
        0,  
        DIGCF_ALLCLASSES | DIGCF_PRESENT ); // All devices present on system 
    if (DeviceInfoSet == INVALID_HANDLE_VALUE) 
    { 
        return DisplayError(TEXT("GetClassDevs(All Present Devices)"));         
    } 
     
    //_tprintf(TEXT("Search for Device ID: [%s]\n"),HardwareId); 
     
    // 
    //  Enumerate through all Devices. 
    // 
    Found = FALSE; 
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 
    for (i=0;SetupDiEnumDeviceInfo(DeviceInfoSet,i,&DeviceInfoData);i++) 
    { 
        DWORD DataT; 
        LPTSTR p,buffer = NULL; 
        DWORD buffersize = 0; 
         
        // 
        // We won't know the size of the HardwareID buffer until we call 
        // this function. So call it with a null to begin with, and then  
        // use the required buffer size to Alloc the nessicary space. 
        // Keep calling we have success or an unknown failure. 
        // 
        while (!SetupDiGetDeviceRegistryProperty( 
            DeviceInfoSet, 
            &DeviceInfoData, 
            SPDRP_HARDWAREID, 
            &DataT, 
            (PBYTE)buffer, 
            buffersize, 
            &buffersize)) 
        { 
            if (GetLastError() == ERROR_INVALID_DATA) 
            { 
                // 
                // May be a Legacy Device with no HardwareID. Continue. 
                // 
                break; 
            } 
            else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
            { 
                // 
                // We need to change the buffer size. 
                // 
                if (buffer)  
                    LocalFree(buffer); 
                buffer = (char *)LocalAlloc(LPTR,buffersize); 
            } 
            else 
            { 
                // 
                // Unknown Failure. 
                // 
                DisplayError(TEXT("GetDeviceRegistryProperty")); 
                goto cleanup_DeviceInfo; 
            }             
        } 
         
        if (GetLastError() == ERROR_INVALID_DATA)  
            continue; 
         
        // 
        // Compare each entry in the buffer multi-sz list with our HardwareID. 
        // 
        for (p=buffer;*p&&(p<&buffer[buffersize]);p+=lstrlen(p)+sizeof(TCHAR)) 
        { 
            //_tprintf(TEXT("Compare device ID: [%s]\n"),p); 
             
            if (!_tcscmp(HardwareId,p)) 
            { 
                //_tprintf(TEXT("Found! [%s]\n"),p); 
                Found = TRUE; 
                break; 
            } 
        } 
         
        if (buffer) LocalFree(buffer); 
        if (Found) break; 
    } 
     
    if (GetLastError() != NO_ERROR) 
    { 
        DisplayError(TEXT("EnumDeviceInfo")); 
    } 
     
    // 
    //  Cleanup. 
    //     
cleanup_DeviceInfo: 
    err = GetLastError(); 
    SetupDiDestroyDeviceInfoList(DeviceInfoSet); 
    SetLastError(err); 
     
    return err == NO_ERROR; //??? 
} 
 
BOOL 
InstallRootEnumeratedDriver(IN  LPTSTR HardwareId, 
    IN  LPTSTR INFFile, 
    OUT PBOOL  RebootRequired  OPTIONAL 
    ) 
{ 
    HDEVINFO DeviceInfoSet = 0; 
    SP_DEVINFO_DATA DeviceInfoData; 
    GUID ClassGUID; 
    TCHAR ClassName[MAX_CLASS_NAME_LEN]; 
    DWORD err; 
     
    // 
    // Use the INF File to extract the Class GUID.  
    // 
    if (!SetupDiGetINFClass(INFFile,&ClassGUID,ClassName,sizeof(ClassName),0)) 
    { 
        return DisplayError(TEXT("GetINFClass")); 
    } 
     
    // 
    // Create the container for the to-be-created Device Information Element. 
    // 
    DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0); 
    if(DeviceInfoSet == INVALID_HANDLE_VALUE)  
    { 
        return DisplayError(TEXT("CreateDeviceInfoList")); 
    } 
     
    //  
    // Now create the element.  
    // Use the Class GUID and Name from the INF file. 
    // 
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 
    if (!SetupDiCreateDeviceInfo(DeviceInfoSet, 
        ClassName, 
        &ClassGUID, 
        NULL, 
        0, 
        DICD_GENERATE_ID, 
        &DeviceInfoData)) 
    { 
        DisplayError(TEXT("CreateDeviceInfo")); 
        goto cleanup_DeviceInfo; 
    } 
     
    // 
    // Add the HardwareID to the Device's HardwareID property. 
    // 
    if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, 
        &DeviceInfoData, 
        SPDRP_HARDWAREID, 
        (LPBYTE)HardwareId, 
        (lstrlen(HardwareId)+1+1)*sizeof(TCHAR)))  
    { 
        DisplayError(TEXT("SetDeviceRegistryProperty")); 
        goto cleanup_DeviceInfo; 
    } 
     
    // 
    // Transform the registry element into an actual devnode  
    // in the PnP HW tree. 
    // 
    if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, 
        DeviceInfoSet, 
        &DeviceInfoData)) 
    { 
        DisplayError(TEXT("CallClassInstaller(REGISTERDEVICE)")); 
        goto cleanup_DeviceInfo; 
    } 
     
    // 
    // The element is now registered. We must explicitly remove the  
    // device using DIF_REMOVE, if we encounter any failure from now on. 
    // 
     
    // 
    // Install the Driver. 
    // 
    if (!UpdateDriverForPlugAndPlayDevices(0, 
        HardwareId, 
        INFFile, 
        INSTALLFLAG_FORCE, 
        RebootRequired)) 
    { 
        DWORD err = GetLastError(); 
        DisplayError(TEXT("UpdateDriverForPlugAndPlayDevices")); 
         
        if (!SetupDiCallClassInstaller( 
            DIF_REMOVE, 
            DeviceInfoSet, 
            &DeviceInfoData)) 
        { 
            DisplayError(TEXT("CallClassInstaller(REMOVE)")); 
        } 
        SetLastError(err); 
    } 
     
    // 
    //  Cleanup. 
    //     
cleanup_DeviceInfo: 
    err = GetLastError(); 
    SetupDiDestroyDeviceInfoList(DeviceInfoSet); 
    SetLastError(err); 
     
    return err == NO_ERROR; 
} 
 
int InstallDriver(_TCHAR *InfName, _TCHAR *HardwareID) 
{ 
    WIN32_FIND_DATA FindFileData; 
    BOOL RebootRequired = 0; // Must be cleared. 
	_TCHAR *FName, *HWID; 
	FName = InfName; 
	HWID = HardwareID; 
 
    if (FindFirstFile(FName,&FindFileData)==INVALID_HANDLE_VALUE) 
    { 
        //_tprintf(TEXT("  File not found.\n")); 
        //_tprintf(TEXT("usage: install  \n")); 
        return 2; // Install Failure 
    } 
     
    // 
    // Look to see if this device allready exists. 
    // 
    if (FindExistingDevice(HWID)) 
    { 
        // 
        // No Need to Create a Device Node, just call our API. 
        // 
        if (!UpdateDriverForPlugAndPlayDevices(0, // No Window Handle 
            HWID, // Hardware ID 
            FName, // FileName 
            INSTALLFLAG_FORCE, 
            &RebootRequired)) 
        { 
            DisplayError(TEXT("UpdateDriverForPlugAndPlayDevices")); 
            return 2; // Install Failure 
        } 
    } 
    else 
    { 
        if (GetLastError()!= ERROR_NO_MORE_ITEMS) 
        { 
            // 
            // An unknown failure from FindExistingDevice() 
            // 
			//_tprintf(TEXT("(IERROR_NO_MORE_ITEMS)\n")); 
			//_tprintf(TEXT("(Install Failure! Code = 2)\n")); 
            return 2; // Install Failure 
        } 
         
        //  
        // Driver Does not exist, Create and call the API. 
        // HardwareID must be a multi-sz string, which argv[2] is. 
        // 
        if (!InstallRootEnumeratedDriver(HWID, // HardwareID 
            FName, // FileName 
            &RebootRequired)) 
        { 
			//_tprintf(TEXT("(InstallRootEnumeratedDriver Failure! Code = 2)\n")); 
			return 2; // Install Failure 
        } 
    } 
     
    //_tprintf(TEXT("Driver Installed successfully.\n")); 
     
    if (RebootRequired) 
    { 
        //_tprintf(TEXT("(Reboot Required)\n")); 
        return 1; // Install Success, reboot required. 
    } 
     
    return 0; // Install Success, no reboot required. 
} 
 
int RemoveDriver(_TCHAR *HardwareID) 
{ 
    HDEVINFO DeviceInfoSet; 
    SP_DEVINFO_DATA DeviceInfoData; 
    DWORD i,err; 
 
    DeviceInfoSet = SetupDiGetClassDevs(NULL, // All Classes 
        0, 
        0,  
        DIGCF_ALLCLASSES | DIGCF_PRESENT ); // All devices present on system 
    if (DeviceInfoSet == INVALID_HANDLE_VALUE) 
    { 
        DisplayError(TEXT("GetClassDevs(All Present Devices)"));         
        return 1; 
    } 
     
    // 
    //  Enumerate through all Devices. 
    // 
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 
    for (i=0;SetupDiEnumDeviceInfo(DeviceInfoSet,i,&DeviceInfoData);i++) 
    { 
        DWORD DataT; 
        LPTSTR p,buffer = NULL; 
        DWORD buffersize = 0; 
         
        // 
        // We won't know the size of the HardwareID buffer until we call 
        // this function. So call it with a null to begin with, and then  
        // use the required buffer size to Alloc the nessicary space. 
        // Keep calling we have success or an unknown failure. 
        // 
        while (!SetupDiGetDeviceRegistryProperty( 
            DeviceInfoSet, 
            &DeviceInfoData, 
            SPDRP_HARDWAREID, 
            &DataT, 
            (PBYTE)buffer, 
            buffersize, 
            &buffersize)) 
        { 
            if (GetLastError() == ERROR_INVALID_DATA) 
            { 
                // 
                // May be a Legacy Device with no HardwareID. Continue. 
                // 
                break; 
            } 
            else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
            { 
                // 
                // We need to change the buffer size. 
                // 
                if (buffer)  
                    LocalFree(buffer); 
                buffer = (char *)LocalAlloc(LPTR,buffersize); 
            } 
            else 
            { 
                // 
                // Unknown Failure. 
                // 
                DisplayError(TEXT("GetDeviceRegistryProperty")); 
                goto cleanup_DeviceInfo; 
            }             
        } 
 
        if (GetLastError() == ERROR_INVALID_DATA)  
            continue; 
         
        // 
        // Compare each entry in the buffer multi-sz list with our HardwareID. 
        // 
        for (p=buffer;*p&&(p<&buffer[buffersize]);p+=lstrlen(p)+sizeof(TCHAR)) 
        { 
            //_tprintf(TEXT("Compare device ID: [%s]\n"),p); 
 
            if (!_tcscmp(HardwareID,p)) 
            { 
                //_tprintf(TEXT("Found! [%s]\n"),p); 
 
                // 
                // Worker function to remove device. 
                // 
                if (!SetupDiCallClassInstaller(DIF_REMOVE, 
                    DeviceInfoSet, 
                    &DeviceInfoData)) 
                { 
                    DisplayError(TEXT("CallClassInstaller(REMOVE)")); 
                } 
                break; 
            } 
        } 
 
        if (buffer) LocalFree(buffer); 
    } 
 
    if ((GetLastError()!=NO_ERROR)&&(GetLastError()!=ERROR_NO_MORE_ITEMS)) 
    { 
        DisplayError(TEXT("EnumDeviceInfo")); 
    } 
     
    // 
    //  Cleanup. 
    //     
cleanup_DeviceInfo: 
    err = GetLastError(); 
    SetupDiDestroyDeviceInfoList(DeviceInfoSet); 
     
    return err;  
}