You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1122 lines
37 KiB
1122 lines
37 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 2000
|
|
*
|
|
* TITLE: Entry.cpp
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* AUTHOR: KeisukeT
|
|
*
|
|
* DATE: 27 Mar, 2000
|
|
*
|
|
* DESCRIPTION:
|
|
* Co/Installer/DLL entry point.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
//
|
|
// Precompiled header
|
|
//
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Include
|
|
//
|
|
|
|
|
|
#include "sti_ci.h"
|
|
#include <setupapi.h>
|
|
|
|
#include "firstpg.h"
|
|
#include "portsel.h"
|
|
#include "nameit.h"
|
|
#include "finalpg.h"
|
|
#include "prevpg.h"
|
|
#include "device.h"
|
|
#include "stiregi.h"
|
|
|
|
#include "userdbg.h"
|
|
|
|
//
|
|
// Global
|
|
//
|
|
|
|
HINSTANCE g_hDllInstance = NULL;
|
|
|
|
//
|
|
// Function
|
|
//
|
|
|
|
extern "C"
|
|
BOOL
|
|
APIENTRY
|
|
DllMain(
|
|
IN HINSTANCE hDll,
|
|
IN ULONG ulReason,
|
|
IN LPVOID lpReserved
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DllMain
|
|
|
|
Entrypoint when this DLL is loaded.
|
|
|
|
Arguments:
|
|
|
|
IN HINSTANCE hDll Handle to this DLL instance.
|
|
IN ULONG ulReason The reason this entry is called.
|
|
IN LPVOID lpReserved
|
|
|
|
Return Value:
|
|
|
|
TRUE always.
|
|
|
|
Side effects:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
if (ulReason == DLL_PROCESS_ATTACH) {
|
|
|
|
//
|
|
// Initialize globals.
|
|
//
|
|
|
|
g_hDllInstance = hDll;
|
|
|
|
//
|
|
// Initialize Fusion
|
|
//
|
|
SHFusionInitializeFromModuleID( hDll, 123 );
|
|
|
|
DisableThreadLibraryCalls(hDll);
|
|
InitCommonControls();
|
|
|
|
DBG_INIT(g_hDllInstance);
|
|
// MyDebugInit();
|
|
|
|
}
|
|
else if (ulReason == DLL_PROCESS_DETACH) {
|
|
//
|
|
// Shutdown Fusion
|
|
//
|
|
SHFusionUninitialize();
|
|
}
|
|
|
|
return TRUE;
|
|
} // DllMain ()
|
|
|
|
|
|
extern "C"
|
|
DWORD
|
|
APIENTRY
|
|
ClassInstall (
|
|
IN DI_FUNCTION diFunction,
|
|
IN HDEVINFO hDevInfo,
|
|
IN PSP_DEVINFO_DATA pDevInfoData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ClassInstall
|
|
|
|
Entrypoint of WIA class installer.
|
|
|
|
Arguments:
|
|
|
|
IN DI_FUNCTION diFunction Function to perform.
|
|
IN HDEVINFO hDevInfo, Handle to Device Information.
|
|
IN PSP_DEVINFO_DATA pDevInfoData Pointer to Device Data.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Operation succeeded.
|
|
ERROR_DI_DO_DEFAULT - Operation succeeded, or failed but let it continue.
|
|
Other - Operation failed and unable to continue.
|
|
|
|
Side effects:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD dwReturn;
|
|
DWORD dwError;
|
|
DWORD dwSize;
|
|
SP_INSTALLWIZARD_DATA InstallWizardData;
|
|
SP_DEVINSTALL_PARAMS spDevInstallParams;
|
|
BOOL fCleanupContext;
|
|
PINSTALLER_CONTEXT pInstallerContext;
|
|
|
|
DebugTrace(TRACE_PROC_ENTER,(("ClassInstall: Enter... \r\n")));
|
|
DebugTrace(TRACE_STATUS,(("ClassInstall: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
|
|
|
|
//
|
|
// Initialize locals.
|
|
//
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
dwError = ERROR_SUCCESS;
|
|
dwSize = 0;
|
|
fCleanupContext = FALSE;
|
|
pInstallerContext = NULL;
|
|
|
|
memset(&InstallWizardData, 0, sizeof(InstallWizardData));
|
|
memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
|
|
|
|
//
|
|
// Dispatch requests.
|
|
//
|
|
|
|
switch(diFunction){
|
|
|
|
case DIF_INSTALLWIZARD:
|
|
{
|
|
|
|
fCleanupContext = TRUE;
|
|
|
|
//
|
|
// Get install parameter(s).
|
|
//
|
|
|
|
InstallWizardData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
|
if(!SetupDiGetClassInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&InstallWizardData.ClassInstallHeader,
|
|
sizeof(InstallWizardData),
|
|
NULL) )
|
|
{
|
|
dwError = GetLastError();
|
|
// DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed. Err=0x%x. dwSize=0x%x\n"), dwError, dwSize));
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed. Err=0x%x\n"), dwError));
|
|
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// Check if operation is correct.
|
|
//
|
|
|
|
if (InstallWizardData.ClassInstallHeader.InstallFunction != diFunction) {
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! InstallHeader.InstallFunction is incorrect..\r\n")));
|
|
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// Check if we still have enough room to add pages.
|
|
//
|
|
|
|
if( (MAX_INSTALLWIZARD_DYNAPAGES - NUM_WIA_PAGES) < InstallWizardData.NumDynamicPages ){
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! No room for WIA installer pages.\r\n")));
|
|
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// Allocate context structure.
|
|
//
|
|
|
|
if(NULL == InstallWizardData.PrivateData){
|
|
pInstallerContext = new INSTALLER_CONTEXT;
|
|
if(NULL == pInstallerContext){
|
|
DebugTrace(TRACE_WARNING,(("ClassInstall: ERROR!! Insufficient memory.\r\n")));
|
|
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
goto ClassInstall_return;
|
|
}
|
|
InstallWizardData.PrivateData = (DWORD_PTR)pInstallerContext;
|
|
memset((PBYTE)pInstallerContext, 0, sizeof(INSTALLER_CONTEXT));
|
|
} else {
|
|
DebugTrace(TRACE_WARNING,(("ClassInstall: WARNING!! Installer context already exists.\r\n")));
|
|
}
|
|
|
|
//
|
|
// See who invoked installer.
|
|
//
|
|
|
|
pInstallerContext->bShowFirstPage = InstallWizardData.PrivateFlags & SCIW_PRIV_SHOW_FIRST;
|
|
pInstallerContext->bCalledFromControlPanal = InstallWizardData.PrivateFlags & SCIW_PRIV_CALLED_FROMCPL;
|
|
|
|
//
|
|
// Save device info set.
|
|
//
|
|
|
|
pInstallerContext->hDevInfo = hDevInfo;
|
|
|
|
//
|
|
// Save wizard windows handle.
|
|
//
|
|
|
|
pInstallerContext->hwndWizard = InstallWizardData.hwndWizardDlg;
|
|
|
|
//
|
|
// Create/Initialize all wizard pages and a device class object.
|
|
//
|
|
|
|
CFirstPage *tempFistPage = new CFirstPage(pInstallerContext);
|
|
CPrevSelectPage *tempPrevSelectPage = new CPrevSelectPage(pInstallerContext);
|
|
CPortSelectPage *tempPortSelectPage = new CPortSelectPage(pInstallerContext);
|
|
CNameDevicePage *tempNameDevicePage = new CNameDevicePage(pInstallerContext);
|
|
CInstallPage *tempInstallPage = new CInstallPage(pInstallerContext);
|
|
|
|
if( (NULL == tempFistPage)
|
|
|| (NULL == tempPrevSelectPage)
|
|
|| (NULL == tempPortSelectPage)
|
|
|| (NULL == tempNameDevicePage)
|
|
|| (NULL == tempInstallPage) )
|
|
{
|
|
DebugTrace(TRACE_WARNING,(("ClassInstall: ERROR!! Insufficient memory.\r\n")));
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// Save created to context.
|
|
//
|
|
|
|
pInstallerContext->pFirstPage = (PVOID) tempFistPage;
|
|
pInstallerContext->pPrevSelectPage = (PVOID) tempPrevSelectPage;
|
|
pInstallerContext->pPortSelectPage = (PVOID) tempPortSelectPage;
|
|
pInstallerContext->pNameDevicePage = (PVOID) tempNameDevicePage;
|
|
pInstallerContext->pFinalPage = (PVOID) tempInstallPage;
|
|
|
|
//
|
|
// Add created pages.
|
|
//
|
|
|
|
InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempFistPage->Handle();
|
|
InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempPrevSelectPage->Handle();
|
|
InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempPortSelectPage->Handle();
|
|
InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempNameDevicePage->Handle();
|
|
InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempInstallPage->Handle();
|
|
|
|
//
|
|
// Indicate "pages are added".
|
|
//
|
|
|
|
InstallWizardData.DynamicPageFlags |= DYNAWIZ_FLAG_PAGESADDED;
|
|
|
|
//
|
|
// Set the parameters back.
|
|
//
|
|
|
|
SetupDiSetClassInstallParams (hDevInfo,
|
|
pDevInfoData,
|
|
&InstallWizardData.ClassInstallHeader,
|
|
sizeof(InstallWizardData));
|
|
|
|
fCleanupContext = FALSE;
|
|
dwReturn = NO_ERROR;
|
|
goto ClassInstall_return;
|
|
break;
|
|
|
|
} // case DIF_INSTALLWIZARD:
|
|
|
|
|
|
case DIF_DESTROYWIZARDDATA:
|
|
{
|
|
|
|
//
|
|
// Get install parameter(s).
|
|
//
|
|
|
|
InstallWizardData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
|
if(!SetupDiGetClassInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&InstallWizardData.ClassInstallHeader,
|
|
sizeof(InstallWizardData),
|
|
&dwSize) )
|
|
{
|
|
dwError = GetLastError();
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed. Err=0x%x\n"), dwError));
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
// //
|
|
// // Check if operation is correct.
|
|
// //
|
|
//
|
|
// if (InstallWizardData.ClassInstallHeader.InstallFunction != diFunction) {
|
|
// DebugTrace(TRACE_WARNING,(("ClassInstall: ERROR!! InstallHeader.InstallFunction is incorrect..\r\n")));
|
|
//
|
|
// dwReturn = ERROR_DI_DO_DEFAULT;
|
|
// goto ClassInstall_return;
|
|
// }
|
|
|
|
//
|
|
// Free all allocated resources.
|
|
//
|
|
|
|
fCleanupContext = TRUE;
|
|
pInstallerContext = (PINSTALLER_CONTEXT)InstallWizardData.PrivateData;
|
|
InstallWizardData.PrivateData = NULL;
|
|
|
|
dwReturn = NO_ERROR;
|
|
goto ClassInstall_return;
|
|
break;
|
|
|
|
} // case DIF_DESTROYWIZARDDATA:
|
|
|
|
case DIF_INSTALLDEVICE:
|
|
{
|
|
BOOL bSucceeded;
|
|
BOOL bIsPnp;
|
|
|
|
//
|
|
// Sanity check of DevInfoSet and DevInfoData.
|
|
//
|
|
|
|
if( (NULL == pDevInfoData)
|
|
|| (!IS_VALID_HANDLE(hDevInfo)) )
|
|
{
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Wrong Infoset(0x%x) or instance(0x%x). Unable to continue.\r\n"),pDevInfoData,hDevInfo));
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// Get device install parameters.
|
|
//
|
|
|
|
memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
|
|
spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if(!SetupDiGetDeviceInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&spDevInstallParams))
|
|
{
|
|
DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), GetLastError()));
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// Check NULL driver installation.
|
|
//
|
|
|
|
if(spDevInstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL){
|
|
|
|
//
|
|
// Installing NULL driver. Let default handler handle it.
|
|
//
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
} // if(spDevInstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
|
|
|
|
//
|
|
// See if it's root-enumerated or not.
|
|
//
|
|
|
|
if(IsDeviceRootEnumerated(hDevInfo, pDevInfoData)){
|
|
bIsPnp = FALSE;
|
|
} else {
|
|
bIsPnp = TRUE;
|
|
}
|
|
|
|
//
|
|
// Create CDevice class.
|
|
//
|
|
//
|
|
// Start the WIA service. We start it here so that it will be running when we finish, so
|
|
// it will receive the PnP device arrival notification.
|
|
// Notice we don't change the startup-type here - this will be done later if the device
|
|
// installation was successful.
|
|
//
|
|
|
|
StartWiaService();
|
|
|
|
CDevice cdThis(hDevInfo, pDevInfoData, bIsPnp);
|
|
|
|
//
|
|
// Let it create unique FriendlyName.
|
|
//
|
|
|
|
bSucceeded = cdThis.NameDefaultUniqueName();
|
|
if(bSucceeded){
|
|
|
|
//
|
|
// Do pre-installation process.
|
|
//
|
|
|
|
bSucceeded = cdThis.PreInstall();
|
|
if(bSucceeded){
|
|
|
|
//
|
|
// Do actual installation.
|
|
//
|
|
|
|
bSucceeded = cdThis.Install();
|
|
if(!bSucceeded){
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Installation failed in CDevice class.\r\n")));
|
|
}
|
|
} else {
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! PreInstall failed in CDevice class.\r\n")));
|
|
}
|
|
} else {
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! NameDefaultUniqueName failed in CDevice class.\r\n")));
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
}
|
|
|
|
if(bSucceeded){
|
|
|
|
//
|
|
// So far, installation is working fine. Do final touch.
|
|
//
|
|
|
|
bSucceeded = cdThis.PostInstall(TRUE);
|
|
if(!bSucceeded){
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! PostInstall failed in CDevice class.\r\n")));
|
|
}
|
|
|
|
//
|
|
// At this point, we consider the installation is succeeded.
|
|
//
|
|
|
|
dwReturn = NO_ERROR;
|
|
|
|
//
|
|
// Get device install parameters again.
|
|
//
|
|
|
|
memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
|
|
spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if(!SetupDiGetDeviceInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&spDevInstallParams))
|
|
{
|
|
dwReturn = GetLastError();;
|
|
DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), dwReturn));
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// We need to notify WIA service about new device addition.
|
|
//
|
|
|
|
if(NULL == spDevInstallParams.ClassInstallReserved){
|
|
spDevInstallParams.ClassInstallReserved = (ULONG_PTR)new CLEANUPITEM;
|
|
if(NULL != spDevInstallParams.ClassInstallReserved){
|
|
memset((PVOID)(spDevInstallParams.ClassInstallReserved), 0, sizeof(CLEANUPITEM));
|
|
} else { // if(NULL == spDevInstallParams.ClassInstallReserved)
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Unable to allocate CLEANUPITEM.\r\n")));
|
|
}
|
|
} // if(NULL == spDevInstallParams.ClassInstallReserved)
|
|
|
|
if(NULL != spDevInstallParams.ClassInstallReserved){
|
|
((PCLEANUPITEM)spDevInstallParams.ClassInstallReserved)->bInstalled = TRUE;
|
|
if(SetupDiSetDeviceInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&spDevInstallParams))
|
|
{
|
|
//
|
|
// Installation succeeded.
|
|
//
|
|
|
|
DebugTrace(TRACE_STATUS,(("ClassInstall: WIA service will reenumerate device.\r\n")));
|
|
} else {
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiSetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError()));
|
|
}
|
|
} else { // if(NULL != spDevInstallParams.ClassInstallReserved)
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! No CLEANUPITEM in context.\r\n")));
|
|
} // else(NULL != spDevInstallParams.ClassInstallReserved)
|
|
|
|
} else {
|
|
|
|
//
|
|
// There's an error during installation. Revert.
|
|
//
|
|
|
|
cdThis.PostInstall(FALSE);
|
|
dwReturn = ERROR_DI_DONT_INSTALL;
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: Reverting installation...\r\n")));
|
|
}
|
|
|
|
goto ClassInstall_return;
|
|
break;
|
|
} // case DIF_INSTALLDEVICE:
|
|
|
|
case DIF_REMOVE:
|
|
{
|
|
|
|
SP_REMOVEDEVICE_PARAMS rdp;
|
|
|
|
//
|
|
// Check if operation is correct.
|
|
//
|
|
|
|
memset (&rdp, 0, sizeof(SP_REMOVEDEVICE_PARAMS));
|
|
rdp.ClassInstallHeader.cbSize = sizeof (SP_CLASSINSTALL_HEADER);
|
|
if (!SetupDiGetClassInstallParams (hDevInfo,
|
|
pDevInfoData,
|
|
&rdp.ClassInstallHeader,
|
|
sizeof(SP_REMOVEDEVICE_PARAMS),
|
|
NULL))
|
|
{
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed Err=0x%x.\r\n"), GetLastError()));
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
} // if (!SetupDiGetClassInstallParams ()
|
|
|
|
if (rdp.ClassInstallHeader.InstallFunction != DIF_REMOVE) {
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// Create CDevice object.
|
|
//
|
|
|
|
CDevice cdThis(hDevInfo, pDevInfoData, TRUE);
|
|
|
|
//
|
|
// Remove the device.
|
|
//
|
|
|
|
dwReturn = cdThis.Remove(&rdp);
|
|
|
|
//
|
|
// Get device install parameters.
|
|
//
|
|
|
|
memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
|
|
spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if(!SetupDiGetDeviceInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&spDevInstallParams))
|
|
{
|
|
dwReturn = GetLastError();;
|
|
DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), dwReturn));
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// We need to notify WIA service about new device addition.
|
|
//
|
|
|
|
if(NULL == spDevInstallParams.ClassInstallReserved){
|
|
spDevInstallParams.ClassInstallReserved = (ULONG_PTR)new CLEANUPITEM;
|
|
if(NULL != spDevInstallParams.ClassInstallReserved){
|
|
memset((PVOID)(spDevInstallParams.ClassInstallReserved), 0, sizeof(CLEANUPITEM));
|
|
} else { // if(NULL == spDevInstallParams.ClassInstallReserved)
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Unable to allocate CLEANUPITEM.\r\n")));
|
|
}
|
|
} // if(NULL == spDevInstallParams.ClassInstallReserved)
|
|
|
|
if(NULL != spDevInstallParams.ClassInstallReserved){
|
|
((PCLEANUPITEM)spDevInstallParams.ClassInstallReserved)->bRemoved = TRUE;
|
|
if(SetupDiSetDeviceInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&spDevInstallParams))
|
|
{
|
|
//
|
|
// Installation succeeded.
|
|
//
|
|
|
|
DebugTrace(TRACE_STATUS,(("ClassInstall: WIA service will reenumerate device.\r\n")));
|
|
|
|
} else {
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiSetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError()));
|
|
}
|
|
} else { // if(NULL != spDevInstallParams.ClassInstallReserved)
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! No CLEANUPITEM in context.\r\n")));
|
|
} // else(NULL != spDevInstallParams.ClassInstallReserved)
|
|
|
|
goto ClassInstall_return;
|
|
break;
|
|
} // case DIF_REMOVE:
|
|
|
|
case DIF_SELECTBESTCOMPATDRV:
|
|
{
|
|
SP_DRVINSTALL_PARAMS spDriverInstallParams;
|
|
SP_DRVINFO_DATA spDriverInfoData;
|
|
PSP_DRVINFO_DETAIL_DATA pspDriverInfoDetailData;
|
|
DWORD dwLastError;
|
|
DWORD dwSizeLocal;
|
|
DWORD Idx;
|
|
|
|
|
|
//
|
|
// Get driver info.
|
|
//
|
|
|
|
memset(&spDriverInfoData, 0, sizeof(spDriverInfoData));
|
|
spDriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
for(Idx = 0; SetupDiEnumDriverInfo(hDevInfo, pDevInfoData, SPDIT_COMPATDRIVER, Idx, &spDriverInfoData); Idx++){
|
|
|
|
//
|
|
// Get driver install params.
|
|
//
|
|
|
|
memset(&spDriverInstallParams, 0, sizeof(spDriverInstallParams));
|
|
spDriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
|
|
if(!SetupDiGetDriverInstallParams(hDevInfo, pDevInfoData, &spDriverInfoData, &spDriverInstallParams)){
|
|
DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInstallParams() failed LastError=0x%x.\r\n", GetLastError()));
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
} // if(!SetupDiGetDriverInstallParams(hDevInfo, pDevInfoData, &spDriverInfoData, &spDriverInstallParams))
|
|
|
|
//
|
|
// Get buffer size required for driver derail data.
|
|
//
|
|
|
|
dwSizeLocal = 0;
|
|
SetupDiGetDriverInfoDetail(hDevInfo,
|
|
pDevInfoData,
|
|
&spDriverInfoData,
|
|
NULL,
|
|
0,
|
|
&dwSizeLocal);
|
|
dwLastError = GetLastError();
|
|
if(ERROR_INSUFFICIENT_BUFFER != dwLastError){
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() doesn't return required size.Er=0x%x\r\n"),dwLastError));
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
} // if(ERROR_INSUFFICIENT_BUFFER != dwLastError)
|
|
|
|
//
|
|
// Allocate required size of buffer for driver detailed data.
|
|
//
|
|
|
|
pspDriverInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)new char[dwSizeLocal];
|
|
if(NULL == pspDriverInfoDetailData){
|
|
DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Unable to allocate driver detailed info buffer.\r\n")));
|
|
|
|
dwReturn = ERROR_DI_DO_DEFAULT;
|
|
goto ClassInstall_return;
|
|
} // if(NULL == pspDriverInfoDetailData)
|
|
|
|
//
|
|
// Initialize allocated buffer.
|
|
//
|
|
|
|
memset(pspDriverInfoDetailData, 0, dwSizeLocal);
|
|
pspDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
|
|
|
|
//
|
|
// Get detailed data of selected device driver.
|
|
//
|
|
|
|
if(!SetupDiGetDriverInfoDetail(hDevInfo,
|
|
pDevInfoData,
|
|
&spDriverInfoData,
|
|
pspDriverInfoDetailData,
|
|
dwSizeLocal,
|
|
NULL) )
|
|
{
|
|
DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() failed LastError=0x%x.\r\n", GetLastError()));
|
|
|
|
delete[] pspDriverInfoDetailData;
|
|
continue;
|
|
} // if(NULL == pspDriverInfoDetailData)
|
|
|
|
//
|
|
// See if INF filename is valid.
|
|
//
|
|
|
|
if(NULL == pspDriverInfoDetailData->InfFileName){
|
|
DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() returned invalid INF name.\r\n"));
|
|
|
|
delete[] pspDriverInfoDetailData;
|
|
continue;
|
|
} // if(NULL == pspDriverInfoDetailData->InfFileName)
|
|
|
|
//
|
|
// If it's Inbox driver, set DNF_BASIC_DRIVER.
|
|
//
|
|
|
|
if( IsWindowsFile(pspDriverInfoDetailData->InfFileName)
|
|
&& IsProviderMs(pspDriverInfoDetailData->InfFileName ) )
|
|
{
|
|
|
|
//
|
|
// This is inbox INF. set DNF_BASIC_DRIVER.
|
|
//
|
|
|
|
spDriverInstallParams.Flags |= DNF_BASIC_DRIVER;
|
|
SetupDiSetDriverInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&spDriverInfoData,
|
|
&spDriverInstallParams);
|
|
} // if(IsWindowsFilw() && IsProviderMs())
|
|
|
|
//
|
|
// Clean up.
|
|
//
|
|
|
|
delete[] pspDriverInfoDetailData;
|
|
|
|
} // for(Idx = 0; SetupDiEnumDriverInfo(hDevInfo, pDevInfoData, SPDIT_COMPATDRIVER, Idx, &spDriverInfoData), Idx++)
|
|
|
|
goto ClassInstall_return;
|
|
break;
|
|
} // case DIF_SELECTBESTCOMPATDRV:
|
|
|
|
case DIF_DESTROYPRIVATEDATA:
|
|
{
|
|
PCLEANUPITEM pCleanupItem;
|
|
|
|
//
|
|
// Get device install parameters.
|
|
//
|
|
|
|
spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if(!SetupDiGetDeviceInstallParams(hDevInfo,
|
|
pDevInfoData,
|
|
&spDevInstallParams))
|
|
{
|
|
dwReturn = GetLastError();;
|
|
DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), dwReturn));
|
|
goto ClassInstall_return;
|
|
}
|
|
|
|
//
|
|
// See if any cleanup required.
|
|
//
|
|
|
|
pCleanupItem = (PCLEANUPITEM)spDevInstallParams.ClassInstallReserved;
|
|
if(NULL != pCleanupItem){
|
|
|
|
//
|
|
// A device is installed/uninstalled.
|
|
//
|
|
|
|
DebugTrace(TRACE_STATUS,("ClassInstall: Clean up item is created..\r\n"));
|
|
|
|
if( (TRUE == pCleanupItem->bInstalled)
|
|
|| (TRUE == pCleanupItem->bRemoved) )
|
|
{
|
|
DebugTrace(TRACE_STATUS,("ClassInstall: Let WIA service refresh device list.\r\n"));
|
|
WiaDeviceEnum();
|
|
}
|
|
|
|
delete pCleanupItem;
|
|
pCleanupItem = NULL;
|
|
} // if(NULL != pCleanupItem)
|
|
} // case DIF_DESTROYPRIVATEDATA:
|
|
|
|
|
|
// case DIF_ENABLECLASS:
|
|
// case DIF_FIRSTTIMESETUP:
|
|
default:
|
|
break;
|
|
|
|
} // switch(diFunction)
|
|
|
|
|
|
ClassInstall_return:
|
|
|
|
|
|
if(fCleanupContext){
|
|
if(NULL != pInstallerContext){
|
|
|
|
|
|
if(NULL != pInstallerContext->pFirstPage){
|
|
delete (CFirstPage *)(pInstallerContext->pFirstPage);
|
|
}
|
|
if(NULL != pInstallerContext->pPrevSelectPage){
|
|
delete (CPrevSelectPage *)(pInstallerContext->pPrevSelectPage);
|
|
}
|
|
if(NULL != pInstallerContext->pPortSelectPage){
|
|
delete (CPortSelectPage *)(pInstallerContext->pPortSelectPage);
|
|
}
|
|
if(NULL != pInstallerContext->pNameDevicePage){
|
|
delete (CNameDevicePage *)(pInstallerContext->pNameDevicePage);
|
|
}
|
|
if(NULL != pInstallerContext->pFinalPage){
|
|
delete (CInstallPage *)(pInstallerContext->pFinalPage);
|
|
}
|
|
|
|
//
|
|
// Removed this delete call for the pDevice pointer. The Wizard pages
|
|
// delete this memory when a user presses "cancel" or closes the Wizard
|
|
// dialog.
|
|
//
|
|
// COOPP - 01-18-2001. Quick fix to BUG #284981 Heap Corruption
|
|
//
|
|
// Note for future: As discussed with KeisukeT, a better design would be
|
|
// adding a shared pInstallerContext pointer in the BASE class of the
|
|
// Wizard pages. This would allow this routine to remain enabled as a
|
|
// "catch-all" case. (Catching the case if the Wizard dialogs did not free
|
|
// the memory first)
|
|
//
|
|
// if(NULL != pInstallerContext->pDevice){
|
|
// delete pInstallerContext->pDevice;
|
|
//}
|
|
//
|
|
|
|
delete pInstallerContext;
|
|
} // if(NULL != pInstallerContext)
|
|
}
|
|
|
|
DebugTrace(TRACE_PROC_LEAVE,(("ClassInstall: Leaving... Ret=0x%x.\r\n"), dwReturn));
|
|
return dwReturn;
|
|
} // ClassInstall()
|
|
|
|
|
|
extern "C"
|
|
DWORD
|
|
APIENTRY
|
|
CoinstallerEntry(
|
|
IN DI_FUNCTION diFunction,
|
|
IN HDEVINFO hDevInfo,
|
|
IN PSP_DEVINFO_DATA pDevInfoData,
|
|
IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
CoinstallerEntry
|
|
|
|
Entrypoint of WIA class coinstaller.
|
|
|
|
Arguments:
|
|
|
|
IN DI_FUNCTION diFunction, Function to perform.
|
|
IN HDEVINFO hDevInfo, Handle to Device Information.
|
|
IN PSP_DEVINFO_DATA pDevInfoData, Pointer to Device Data.
|
|
IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext Context data for coinstaller.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Operation succeeded.
|
|
ERROR_DI_POSTPROCESSING_REQUIRED - Need post processing after installation has done.
|
|
|
|
Side effects:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
DebugTrace(TRACE_PROC_ENTER,(("CoinstallerEntry: Enter... \r\n")));
|
|
|
|
//
|
|
// Initialize local.
|
|
//
|
|
|
|
dwReturn = NO_ERROR;
|
|
|
|
//
|
|
// Do Pre/Post process.
|
|
//
|
|
|
|
if(pCoinstallerContext->PostProcessing){
|
|
|
|
//
|
|
// Do post-process.
|
|
//
|
|
|
|
dwReturn = CoinstallerPostProcess(diFunction,
|
|
hDevInfo,
|
|
pDevInfoData,
|
|
pCoinstallerContext);
|
|
} else {
|
|
|
|
//
|
|
// Do pre-process.
|
|
//
|
|
|
|
dwReturn = CoinstallerPreProcess(diFunction,
|
|
hDevInfo,
|
|
pDevInfoData,
|
|
pCoinstallerContext);
|
|
} // if(pCoinstallerContext->PostProcessing)
|
|
|
|
// CoinstallerEntry_return:
|
|
DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerEntry: Leaving... Ret=0x%x.\r\n"), dwReturn));
|
|
return dwReturn;
|
|
|
|
} // CoinstallerEntry()
|
|
|
|
|
|
|
|
DWORD
|
|
APIENTRY
|
|
CoinstallerPreProcess(
|
|
IN DI_FUNCTION diFunction,
|
|
IN HDEVINFO hDevInfo,
|
|
IN PSP_DEVINFO_DATA pDevInfoData,
|
|
IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
|
|
)
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
DebugTrace(TRACE_PROC_ENTER,(("CoinstallerPreProcess: Enter... \r\n")));
|
|
DebugTrace(TRACE_STATUS,(("CoinstallerPreProcess: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
|
|
|
|
//
|
|
// Initialize local.
|
|
//
|
|
|
|
dwReturn = NO_ERROR;
|
|
|
|
//
|
|
// Dispatch requests.
|
|
//
|
|
|
|
switch(diFunction){
|
|
|
|
case DIF_INSTALLDEVICE:
|
|
{
|
|
BOOL bSucceeded;
|
|
|
|
//
|
|
// Initialize private data.
|
|
//
|
|
|
|
if(NULL != pCoinstallerContext->PrivateData){
|
|
DebugTrace(TRACE_WARNING,(("CoinstallerPreProcess: WARNING!! Private has value other than NULL.\r\n")));
|
|
}
|
|
pCoinstallerContext->PrivateData = NULL;
|
|
|
|
//
|
|
// Create CDevice class.
|
|
//
|
|
|
|
CDevice *pDevice = new CDevice(hDevInfo, pDevInfoData, TRUE);
|
|
if(NULL == pDevice){
|
|
DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! Insufficient memory.\r\n")));
|
|
dwReturn = NO_ERROR;
|
|
goto CoinstallerPreProcess_return;
|
|
} // if(NULL == pDevice)
|
|
|
|
//
|
|
// Let it create unique FriendlyName.
|
|
//
|
|
|
|
bSucceeded = pDevice->NameDefaultUniqueName();
|
|
if(bSucceeded){
|
|
|
|
//
|
|
// Do pre-installation process.
|
|
//
|
|
|
|
bSucceeded = pDevice->PreInstall();
|
|
if(!bSucceeded){
|
|
DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! Pre-Installation failed in CDevice class.\r\n")));
|
|
delete pDevice;
|
|
|
|
dwReturn = NO_ERROR;
|
|
goto CoinstallerPreProcess_return;
|
|
}
|
|
} else {
|
|
DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! NameDefaultUniqueName failed in CDevice class.\r\n")));
|
|
delete pDevice;
|
|
|
|
dwReturn = NO_ERROR;
|
|
goto CoinstallerPreProcess_return;
|
|
}
|
|
|
|
//
|
|
// Post-installation have to free allocated object.
|
|
//
|
|
|
|
pCoinstallerContext->PrivateData = (PVOID)pDevice;
|
|
dwReturn = ERROR_DI_POSTPROCESSING_REQUIRED;
|
|
|
|
goto CoinstallerPreProcess_return;
|
|
break;
|
|
} // case DIF_INSTALLDEVICE:
|
|
|
|
default:
|
|
break;
|
|
} // switch(diFunction)
|
|
|
|
CoinstallerPreProcess_return:
|
|
DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerPreProcess: Leaving... Ret=0x%x.\r\n"), dwReturn));
|
|
return dwReturn;
|
|
} // CoinstallerPreProcess()
|
|
|
|
|
|
DWORD
|
|
APIENTRY
|
|
CoinstallerPostProcess(
|
|
IN DI_FUNCTION diFunction,
|
|
IN HDEVINFO hDevInfo,
|
|
IN PSP_DEVINFO_DATA pDevInfoData,
|
|
IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
|
|
)
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
DebugTrace(TRACE_PROC_ENTER,(("CoinstallerPostProcess: Enter... \r\n")));
|
|
DebugTrace(TRACE_STATUS,(("CoinstallerPostProcess: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
|
|
|
|
//
|
|
// Initialize local.
|
|
//
|
|
|
|
dwReturn = NO_ERROR;
|
|
|
|
//
|
|
// Dispatch requests.
|
|
//
|
|
|
|
switch(diFunction){
|
|
|
|
case DIF_INSTALLDEVICE:
|
|
{
|
|
BOOL bSucceeded;
|
|
CDevice *pDevice;
|
|
|
|
if(NO_ERROR == pCoinstallerContext->InstallResult){
|
|
bSucceeded = TRUE;
|
|
} else {
|
|
bSucceeded = FALSE;
|
|
}
|
|
//
|
|
// Get pointer to the CDevice class created in pre-process.
|
|
//
|
|
|
|
pDevice = (CDevice *)pCoinstallerContext->PrivateData;
|
|
|
|
//
|
|
// Do post-installation process.
|
|
//
|
|
|
|
pDevice->PostInstall(bSucceeded);
|
|
|
|
//
|
|
// Delete CDevice object.
|
|
//
|
|
|
|
delete pDevice;
|
|
pCoinstallerContext->PrivateData = NULL;
|
|
|
|
dwReturn = NO_ERROR;
|
|
goto CoinstallerPostProcess_return;
|
|
break;
|
|
} // case DIF_INSTALLDEVICE:
|
|
|
|
default:
|
|
break;
|
|
} // switch(diFunction)
|
|
|
|
CoinstallerPostProcess_return:
|
|
DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerPostProcess: Leaving... Ret=0x%x.\r\n"), dwReturn));
|
|
return dwReturn;
|
|
} // CoinstallerPostProcess(
|
|
|
|
|