⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cocpyinf.c

📁 This document accompanies a sample co-installer that can be used in conjunction with an INF file to
💻 C
字号:
//+-----------------------------------------------------------------------------
//
//  Microsoft Windows
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//  File:       COCPYINF.C
//
//  Contents:   co-installer hook to copy INF's into INF directory
//
//              The assumption here is that the install section may
//              specify, eg, "CopyINF = a.inf,b.inf,c.inf"
//              where the inf's specified must exist in same location
//              as primary inf.
//
//              This example shows both a way to install INF's for a
//              multi-function device for Windows 2000, and also how
//              to add to the INF syntax for other purposes.
//
//  Notes:      For a complete description of CoInstallers, please see the
//                 Microsoft Windows 2000 DDK Documentation
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <setupapi.h>
#include <stdio.h>
#include <malloc.h>


//+-----------------------------------------------------------------------------
//
// WARNING!
//
// A Coinstaller must not generate any popup to the user when called with
// DI_QUIETINSTALL. However, it's generally never a good idea to generate
// popups.
//
// OutputDebugString is a fine way to output information for debugging
//
#if DBG
#define DbgOut(Text) OutputDebugString(TEXT("CoCopyInf: " Text "\n"))
#else
#define DbgOut(Text)
#endif

//
// this is the keyword we've introduced by this co-installer
// note that the name is not case sensative
//
#define COPYINF_KEY TEXT("CopyINF")


//+-----------------------------------------------------------------------------
//
//  Function:   IsWindows2000
//
//  Purpose:    Determine if we are running on Windows 2000
//
//  Arguments:   None
//
//  Returns:  TRUE if on Windows 2000, FALSE otherwise
//
BOOL 
IsWindows2000(
    void
    )
{
    OSVERSIONINFO osvi;

    ZeroMemory(&osvi, sizeof(osvi));
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    if (GetVersionEx(&osvi) &&
        (osvi.dwMajorVersion == 5) &&
        (osvi.dwMinorVersion == 0)) {
        
        return TRUE;
    }

    return FALSE;
}

//+-----------------------------------------------------------------------------
//
//  Function:   PostProcessInstallDevice
//
//  Purpose:    Handle DIF_INSTALLDEVICE PostProcessing
//
//  Arguments:
//      DeviceInfoSet     [in]
//      DeviceInfoData    [in]
//      Context           [in,out]
//
//  Returns:    NO_ERROR or an error code.
//
DWORD
PostProcessInstallDevice (
                    IN     HDEVINFO          DeviceInfoSet,
                    IN     PSP_DEVINFO_DATA  DeviceInfoData,
                    IN OUT PCOINSTALLER_CONTEXT_DATA Context
                    )
{
    DWORD                  Status = NO_ERROR;
    INFCONTEXT             InfContext;
    HINF                   InfFile = INVALID_HANDLE_VALUE;
    SP_DRVINFO_DATA        DriverInfoData;
    SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
    PSP_INF_INFORMATION    InfInformation = NULL;
    DWORD                  ReqSize;
    SP_ORIGINAL_FILE_INFO  InfOriginalFileInformation;
    TCHAR                  InstallSectionName[LINE_LEN];
    TCHAR                  CombinedPath[MAX_PATH*2];
    TCHAR                  FullSourcePath[MAX_PATH];
    PTSTR                  FileNamePtr;
    INFCONTEXT             InfLineContext;
    DWORD                  FieldIndex;
    DWORD                  FieldCount;
    DWORD                  RetVal;
    

    //
    // Find name of INF and name of install section
    //
    DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
    if (!SetupDiGetSelectedDriver( DeviceInfoSet,
                                   DeviceInfoData,
                                   &DriverInfoData)) {
        Status = GetLastError();
        DbgOut("Fail: SetupDiGetSelectedDriver");
        goto clean;
    }


    DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
    if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
                                    DeviceInfoData,
                                    &DriverInfoData,
                                    &DriverInfoDetailData,
                                    sizeof(SP_DRVINFO_DETAIL_DATA),
                                    NULL)) {
        Status = GetLastError();
        if (Status == ERROR_INSUFFICIENT_BUFFER) {
            //
            // We don't need the extended information.  Ignore.
            //
        } else {
            DbgOut("Fail: SetupDiGetDriverInfoDetail");
            goto clean;
        }
    }

    //
    // We have InfFileName, open the INF
    //
    InfFile = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
                               NULL,
                               INF_STYLE_WIN4,
                               NULL);
    if (InfFile == INVALID_HANDLE_VALUE) {
        Status = GetLastError();
        DbgOut("Fail: SetupOpenInfFile");
        goto clean;
    }

    //
    // determine original filename to see if it has been
    // previously copied
    // this is long-winded, and is rarely an apropriate thing
    // to do. If we don't do it in this case, we'll try and
    // copy INF files that have already been copied and that
    // we might not have source for.
    //
    ReqSize = 0;
    if (!SetupGetInfInformation(InfFile,
                                INFINFO_INF_SPEC_IS_HINF,
                                NULL,
                                0,
                                &ReqSize)) {
        Status = GetLastError();
        DbgOut("Fail: SetupGetInfInformation");
        goto clean;
    }

    
    InfInformation = (PSP_INF_INFORMATION)malloc(ReqSize);
    if (InfInformation == NULL) {
        Status = ERROR_NOT_ENOUGH_MEMORY;
        DbgOut("Fail: SetupGetInfInformation - malloc");
        goto clean;
    }
    
    if (!SetupGetInfInformation(InfFile,
                                INFINFO_INF_SPEC_IS_HINF,
                                InfInformation,
                                ReqSize,
                                NULL)) {
        Status = GetLastError();
        DbgOut("Fail: SetupGetInfInformation - 2nd call");
        goto clean;
    }


    InfOriginalFileInformation.cbSize = sizeof(InfOriginalFileInformation);
    if(!SetupQueryInfOriginalFileInformation(InfInformation,
                                     0,
                                     NULL,
                                     &InfOriginalFileInformation)) {
        Status = GetLastError();
        DbgOut("Fail: SetupQueryInfOriginalFileInformation");
        goto clean;
    }


    //
    // determine location of current INF, which will be used
    // as root of inf's specified in CopyInf
    // but we also need FileNamePtr here to do an INF Name check.
    //

    RetVal = GetFullPathName(DriverInfoDetailData.InfFileName,
                             MAX_PATH,
                             CombinedPath,
                             &FileNamePtr);
    if (RetVal == 0 || RetVal > MAX_PATH) {
        Status = GetLastError();
        DbgOut("Fail: GetFullPathName");
        goto clean;
    }


    if (lstrcmpi(FileNamePtr,
                 InfOriginalFileInformation.OriginalInfName)!=0) {
        //
        // we have determined that this is a copy of original INF
        // so we must have already processed CopyINF= bits
        //
        Status = NO_ERROR;
        DbgOut("Skip processing of CopyINF (INF not at source location)");
        goto clean;
    }


    //
    // determine section used for the install which might be different
    // from the section name specified in DriverInfoDetailData.
    //
    if(!SetupDiGetActualSectionToInstall(InfFile,
                                         DriverInfoDetailData.SectionName,
                                         InstallSectionName,
                                         LINE_LEN,
                                         NULL,
                                         NULL)) {

        Status = GetLastError();
        DbgOut("Fail: SetupDiGetActualSectionToInstall");
        goto clean;
    }


    //
    // we look for keyword "CopyInf" in the install section
    //
    if (SetupFindFirstLine(InfFile,
                           InstallSectionName,
                           COPYINF_KEY,
                           &InfLineContext)) 
    {
        DbgOut("Found at least one CopyInf entry");
        do {
            //
            // CopyInf = a.inf,b.inf,c.inf...
            // a.inf will be at index 1.
            //
            FieldCount = SetupGetFieldCount(&InfLineContext);
            for(FieldIndex = 1;FieldIndex<=FieldCount;FieldIndex++) {
                if(SetupGetStringField(&InfLineContext,
                                       FieldIndex,
                                       FileNamePtr,
                                       MAX_PATH,
                                       NULL)) {
                    //
                    // we have a listed INF, obtain canonical pathname
                    // for this INF
                    // (note that we assume the INF is relative
                    //  to original INF and is typically just a filename)
                    //
                    RetVal = GetFullPathName(CombinedPath,
                                             MAX_PATH,
                                             FullSourcePath,
                                             NULL);
                    if (RetVal == 0 || RetVal > MAX_PATH) {
                        Status = GetLastError();
                        DbgOut("Fail: GetFullPathName");
                        //
                        // not fatal
                        //
                    } else if(!SetupCopyOEMInf(FullSourcePath,
                                    NULL,
                                    SPOST_PATH,
                                    0,
                                    NULL,
                                    0,
                                    NULL,
                                    NULL)) {
                        Status = GetLastError();
                        DbgOut("Fail: SetupCopyOEMInf");
                        //
                        // not fatal
                        //
                    }
                } else {
                    Status = GetLastError();
                    DbgOut("Fail: SetupGetStringField");
                    //
                    // not fatal
                    //
                }
            }

        } while (SetupFindNextMatchLine(&InfLineContext,
                                        COPYINF_KEY,
                                        &InfLineContext));
    } else {
        DbgOut("No CopyInf entry found");
    }


    Status = NO_ERROR;

clean:


    if (InfInformation) {
        free(InfInformation);
    }
    if (InfFile) {
        SetupCloseInfFile(InfFile);
    }
    //
    // since what we are doing does not affect primary device installation
    // always return success
    //
    return NO_ERROR;
}

//+-----------------------------------------------------------------------------
//
//  Function:   CoCopyINF
//
//  Purpose:    Responds to co-installer messages
//
//  Arguments:
//      InstallFunction   [in]
//      DeviceInfoSet     [in]
//      DeviceInfoData    [in]
//      Context           [in,out]
//
//  Returns:    NO_ERROR, ERROR_DI_POSTPROCESSING_REQUIRED, or an error code.
//
DWORD
__stdcall CoCopyINF (
               IN     DI_FUNCTION               InstallFunction,
               IN     HDEVINFO                  DeviceInfoSet,
               IN     PSP_DEVINFO_DATA          DeviceInfoData,
               IN OUT PCOINSTALLER_CONTEXT_DATA Context
               )
{
    DWORD Status = NO_ERROR;

    switch (InstallFunction)
    {
        case DIF_INSTALLDEVICE:
            //
            // We should not copy any INF files until the install has completed
            // like the primary INF, all secondary INF's must exist on each disk
            // of a multi-disk install.
            //

            if(!Context->PostProcessing)
            {
                DbgOut("DIF_INSTALLDEVICE");

                //
                // We only want the special processing on Windows 2000
                //
                if( IsWindows2000() )
                {
                    //
                    // indicate that we need to be called after the device has been
                    // installed.
                    //
                    DbgOut("Windows 2000, requiring post-processing");
                    Status = ERROR_DI_POSTPROCESSING_REQUIRED;
                }
                else
                {
                    Status = NO_ERROR;
                    DbgOut("Not on Windows 2000, no post-processing required");
                }
                
            }
            else // post processing
            {
                //
                // if driver installation failed, we're not interested
                // in processing CopyINF entries.
                //
                if (Context->InstallResult != NO_ERROR) {
                    DbgOut("DIF_INSTALLDEVICE PostProcessing on failure");
                    Status = Context->InstallResult;
                    break;
                }
                DbgOut("DIF_INSTALLDEVICE PostProcessing");

                Status = PostProcessInstallDevice(DeviceInfoSet,
                                                  DeviceInfoData,
                                                  Context);
            }
        break;

    default:
        break;
    }

    return Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -