|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
external.c
Abstract:
Routines for handling external INFs
Author:
Andrew Ritz (andrewr) 20-Nov-1998
Revision History:
stole a bunch of code from optional.c for this
--*/
#include "setupp.h"
#pragma hdrstop
#include <windowsx.h>
#include <shlobj.h>
VOID ReportError ( IN LogSeverity Severity, IN PTSTR MessageString, IN UINT MessageId, ... )
/*++
Routine Description:
Records an error message in the setup action log if we're in Setup, or puts the message in a dialog box if we're in the cpl.
Arguments:
Severity - the type of message being written
... - the message id and its arguments
Return Value:
nothing.
--*/
{ va_list arglist;
va_start (arglist, MessageId);
SetuplogErrorV( Severity, MessageString, MessageId, &arglist);
va_end (arglist); }
VOID DoRunonce ( )
/*++
Routine Description:
Invokes runonce.
Arguments:
none.
Return Value:
nothing.
--*/
{ #define RUNONCE_TIMEOUT 60*1000*30 //30 minutes
DWORD reRet = NO_ERROR;
if((reRet = pSetupInstallStopEx( FALSE, INSTALLSTOP_NO_UI, NULL)) == NO_ERROR) { //
// We successfully setup the registry values - now do runonce
//
InvokeExternalApplicationEx(NULL, L"RUNONCE -r", &reRet, RUNONCE_TIMEOUT, FALSE);
} else { //
// Log/report an error that registry mods failed for optional compononent.
//
ReportError(LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_REGISTRY_ERROR, TEXT("HKEY_LOCAL_MACHINE\\") REGSTR_PATH_RUNONCE, 0, SETUPLOG_USE_MESSAGEID, reRet, 0, 0 ); }
#ifdef _WIN64
//
// on win64, invoke the 32 bit version of runonce as well
//
{ WCHAR Path[MAX_PATH+50];
ExpandEnvironmentStrings( L"%systemroot%\\SysWOW64\\RUNONCE.EXE -r", Path, sizeof(Path)/sizeof(WCHAR));
InvokeExternalApplicationEx(NULL, Path , &reRet, RUNONCE_TIMEOUT, FALSE);
} #endif
}
BOOL DoInstallComponentInfs( IN HWND hwndParent, IN HWND hProgress, OPTIONAL IN UINT ProgressMessage, IN HINF InfHandle, IN PCWSTR InfSection ) { HINF *hInfs = NULL; PCWSTR *Sections = NULL, *InfNames = NULL; PCWSTR Inf,Section; PVOID p; INFCONTEXT Context; PVOID QContext = NULL; HSPFILEQ FileQueue = INVALID_HANDLE_VALUE; DWORD ScanQueueResult; LONG NumInfs, InfCount, i; DWORD LastErrorValue = ERROR_SUCCESS; BOOL b = FALSE; REGISTRATION_CONTEXT RegistrationContext;
RtlZeroMemory(&RegistrationContext,sizeof(RegistrationContext));
//
// initialize a file queue
//
FileQueue = SetupOpenFileQueue(); if (FileQueue == INVALID_HANDLE_VALUE) { ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, ERROR_NOT_ENOUGH_MEMORY, 0,0); goto e0; }
//
// Initialize the default queue callback.
//
QContext = InitSysSetupQueueCallbackEx( hwndParent, hProgress, ProgressMessage, 0,NULL); if (!QContext) { ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, ERROR_NOT_ENOUGH_MEMORY, 0,0); goto e1; }
//
// process 'mandatory' component infs.
//
NumInfs = SetupGetLineCount(InfHandle, InfSection); if (NumInfs <= 0) { //
// nothing in section. return success for doing nothing
//
b = TRUE; goto e2; }
hInfs = MyMalloc( sizeof(HINF) * NumInfs ); Sections = MyMalloc( sizeof(PCWSTR) * NumInfs ); InfNames = MyMalloc( sizeof(PCWSTR) * NumInfs );
if (!hInfs) { ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, ERROR_NOT_ENOUGH_MEMORY, 0,0); goto e2; }
if (!Sections) { ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, ERROR_NOT_ENOUGH_MEMORY, 0,0); goto e3; }
if (!InfNames) { ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, ERROR_NOT_ENOUGH_MEMORY, 0,0); goto e4; }
RemainingTime = CalcTimeRemaining(Phase_InstallComponentInfs); SetRemainingTime(RemainingTime); BEGIN_SECTION(L"Installing component files"); InfCount = 0; if(SetupFindFirstLine(InfHandle,InfSection,NULL,&Context)) { do { if((Inf = pSetupGetField(&Context,1)) && (Section = pSetupGetField(&Context,2))) { MYASSERT(InfCount < NumInfs);
//
// save away the section name for later on
//
Sections[InfCount] = pSetupDuplicateString(Section); if (!Sections[InfCount]) { ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, ERROR_NOT_ENOUGH_MEMORY, 0,0); goto e6; }
InfNames[InfCount] = pSetupDuplicateString(Inf); if (!InfNames[InfCount]) { ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, ERROR_NOT_ENOUGH_MEMORY, 0,0); goto e6; }
BEGIN_SECTION((PWSTR)Section); SetupDebugPrint2( TEXT("Installing Section [%s] from %s\n"), Section, Inf );
//
// queue files and save away the inf handle for later on
//
hInfs[InfCount] = SetupOpenInfFile(Inf,NULL,INF_STYLE_OLDNT|INF_STYLE_WIN4,NULL); if(hInfs[InfCount] && (hInfs[InfCount] != INVALID_HANDLE_VALUE)) { PCWSTR Signature; INFCONTEXT Cntxt; HINF layout = NULL; if (SetupFindFirstLine( hInfs[InfCount], L"Version",L"Signature", &Cntxt)) { Signature = pSetupGetField(&Cntxt,1); MYASSERT(Signature); if (_wcsicmp(Signature,L"$Windows NT$") == 0) { SetupOpenAppendInfFile(NULL,hInfs[InfCount],NULL); } else { layout = InfCacheOpenLayoutInf(hInfs[InfCount]); } }
b = SetupInstallFilesFromInfSection( hInfs[InfCount], layout, FileQueue, Section, NULL, SP_COPY_NEWER ); if (!b) { //
// report error but continue with the rest of the infs
//
ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_BAD_SECTION, Section, Inf, NULL, SETUPLOG_USE_MESSAGEID, GetLastError(), 0, 0 ); SetupCloseInfFile(hInfs[InfCount]); hInfs[InfCount] = INVALID_HANDLE_VALUE; } } else { //
// failed to open inf file
//
ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_CANT_OPEN_INF, Inf, 0,0); END_SECTION((PWSTR)Section); goto e5; } }
InfCount++; END_SECTION((PWSTR)Section); } while(SetupFindNextLine(&Context,&Context)); } else { // We should have caught this case when we created the buffers!
MYASSERT(FALSE); }
//
// queued all the files. check if we really have to install any files. if not, we can save
// the time required to commit the queue to disk
//
if(!SetupScanFileQueue( FileQueue, SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE, hwndParent, NULL, NULL, &ScanQueueResult)) { //
// SetupScanFileQueue should really never
// fail when you don't ask it to call a
// callback routine, but if it does, just
// go ahead and commit the queue.
//
ScanQueueResult = 0; }
if( ScanQueueResult != 1 ){ b = SetupCommitFileQueue( hwndParent, FileQueue, SysSetupQueueCallback, QContext );
} LastErrorValue = b ? NO_ERROR : GetLastError(); END_SECTION(L"Installing component files");
TermSysSetupQueueCallback(QContext); QContext = NULL;
//
// Delete the file queue.
//
if(FileQueue != INVALID_HANDLE_VALUE) { SetupCloseFileQueue(FileQueue); FileQueue = INVALID_HANDLE_VALUE; }
if (!b) { //
// error commiting the queue. we can't continue at this point since the next operations
// might require the files that we (didn't) copy
//
ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_INF_ALWAYS_ERROR, 0, SETUPLOG_USE_MESSAGEID, LastErrorValue, 0,0); goto e6; }
BEGIN_SECTION(L"Installing component reg settings"); for (i = 0; i< InfCount; i++) { INFCONTEXT Cntxt; TCHAR ScratchSectionName[100]; if (hInfs[i] != INVALID_HANDLE_VALUE) {
//
// if the section contains an Addservice or DelService directive,
// we must explicitly install it since SetupInstallFromInfSection
// does not process services. Note that we create the service
// BEFORE we do the other stuff in the section, in case that
// "other stuff" wants to use the service.
//
lstrcpy( ScratchSectionName, Sections[i]); lstrcat( ScratchSectionName, TEXT(".Services")); if (SetupFindFirstLine( hInfs[i], ScratchSectionName, L"AddService", &Cntxt) || SetupFindFirstLine( hInfs[i], Sections[i], ScratchSectionName, &Cntxt)) {
b = SetupInstallServicesFromInfSectionEx( hInfs[i], ScratchSectionName, 0, NULL, NULL, NULL, NULL); if (!b) { //
// log an error and continue
//
ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_BAD_SECTION, Sections[i],InfNames[i], 0, SETUPLOG_USE_MESSAGEID, GetLastError(), 0,0); } }
b = SetupInstallFromInfSection( hwndParent, hInfs[i], Sections[i], (SPINST_ALL & ~SPINST_FILES) | SPINST_REGISTERCALLBACKAWARE, NULL, NULL, 0, RegistrationQueueCallback, (PVOID)&RegistrationContext, NULL, NULL ); if (!b) { //
// log an error and continue
//
ReportError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_BAD_SECTION, Sections[i],InfNames[i], 0, SETUPLOG_USE_MESSAGEID, GetLastError(), 0,0); }
} } END_SECTION(L"Installing component reg settings");
b = TRUE;
e6: for (i = 0; i < InfCount; i++) {
MYASSERT(Sections != NULL); MYASSERT(InfNames != NULL); MYASSERT(hInfs != INVALID_HANDLE_VALUE);
if (Sections[i]) { MyFree(Sections[i]); }
if (InfNames[i]) { MyFree(InfNames[i]); }
if (hInfs[i] != INVALID_HANDLE_VALUE) { SetupCloseInfFile(hInfs[i]); }
}
e5: if (InfNames) { MyFree(InfNames); } e4: if (Sections) { MyFree(Sections); } e3: if (hInfs) { MyFree(hInfs); } e2: if (QContext) { TermSysSetupQueueCallback(QContext); } e1: if (FileQueue != INVALID_HANDLE_VALUE) { SetupCloseFileQueue(FileQueue); } e0: return(b);
}
BOOL SetupCreateOptionalComponentsPage( IN LPFNADDPROPSHEETPAGE AddPageCallback, IN LPARAM Context ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return( FALSE );
}
BOOL ProcessCompatibilityInfs( IN HWND hwndParent, IN HWND hProgress, OPTIONAL IN UINT ProgressMessage ) { WCHAR UnattendFile[MAX_PATH]; PCWSTR SectionName = pwCompatibility; HINF UnattendInf;
GetSystemDirectory(UnattendFile,MAX_PATH); pSetupConcatenatePaths(UnattendFile,WINNT_GUI_FILE,MAX_PATH,NULL);
UnattendInf = SetupOpenInfFile(UnattendFile,NULL,INF_STYLE_OLDNT,NULL); if(UnattendInf == INVALID_HANDLE_VALUE) { return FALSE; }
DoInstallComponentInfs(hwndParent, hProgress, ProgressMessage, UnattendInf, SectionName );
SetupCloseInfFile( UnattendInf );
return( TRUE );
}
|