#include "setupp.h" #pragma hdrstop #if 0 // This function appears to never be used. BOOL EnqueueFileCopies( IN HINF hInf, IN HSPFILEQ FileQ, IN PCWSTR Section, IN PCWSTR TargetRoot ) { INFCONTEXT InfContext; BOOL LineExists; WCHAR System32Dir[MAX_PATH]; PCWSTR SourceFilename,TargetFilename; BOOL b; GetSystemDirectory(System32Dir,MAX_PATH); LineExists = SetupFindFirstLine(hInf,Section,NULL,&InfContext); while(LineExists) { // // Fetch source and target filenames. // TargetFilename = pSetupGetField(&InfContext,1); if(!TargetFilename) { return(FALSE); } SourceFilename = pSetupGetField(&InfContext,2); if(!SourceFilename) { SourceFilename = TargetFilename; } // // Enqueue the file for copy. // b = SetupQueueCopy( FileQ, System32Dir, NULL, SourceFilename, NULL, NULL, TargetRoot, TargetFilename, BaseCopyStyle ); if(!b) { return(FALSE); } LineExists = SetupFindNextLine(&InfContext,&InfContext); } return(TRUE); } #endif BOOL SideBySidePopulateCopyQueue( SIDE_BY_SIDE* Sxs, HSPFILEQ FileQ, OPTIONAL PCWSTR AssembliesRootSource OPTIONAL ) { BOOL Success = FALSE; UINT SourceId = 0; WCHAR DiskNameBuffer[MAX_PATH]; WCHAR PromptForSetupPath[MAX_PATH]; WCHAR AssembliesRootDirectoryFound[MAX_PATH]; DWORD cchAssembliesRootDirectoryFound = sizeof(AssembliesRootDirectoryFound); DWORD Err; WCHAR AssembliesRootDirectory[MAX_PATH]; PCWSTR InfField = NULL; INFCONTEXT InfContext = {0}; BOOL LineExists = FALSE; SXS_INSTALLW InstallData; SXS_INSTALL_REFERENCEW InstallReference; ASSERT(Sxs != NULL); // // we depend on these having been initialized, and we are not supposed to // be called in MiniSetup or OobeSetup // ASSERT(SourcePath[0] != 0); ASSERT(SyssetupInf != NULL); ASSERT(SyssetupInf != INVALID_HANDLE_VALUE); ASSERT(!MiniSetup); ASSERT(!OobeSetup); // // first, don't fail to give safe values, since we always try to cleanup // Sxs->Dll = NULL; Sxs->BeginAssemblyInstall = NULL; Sxs->EndAssemblyInstall = NULL; Sxs->InstallW = NULL; Sxs->Context = NULL; // // then commence with initialization that can fail // if (!(Sxs->Dll = LoadLibraryW(SXS_DLL_NAME_W))) { goto Exit; } if (!(Sxs->BeginAssemblyInstall = (PSXS_BEGIN_ASSEMBLY_INSTALL)GetProcAddress(Sxs->Dll, SXS_BEGIN_ASSEMBLY_INSTALL))) { goto Exit; } if (!(Sxs->EndAssemblyInstall = (PSXS_END_ASSEMBLY_INSTALL)GetProcAddress(Sxs->Dll, SXS_END_ASSEMBLY_INSTALL))) { goto Exit; } if (!(Sxs->InstallW = (PSXS_INSTALL_W)GetProcAddress(Sxs->Dll, SXS_INSTALL_W))) { goto Exit; } if (!Sxs->BeginAssemblyInstall( SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NOT_TRANSACTIONAL | SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NO_VERIFY | SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_REPLACE_EXISTING, (FileQ != NULL) ? SXS_INSTALLATION_FILE_COPY_CALLBACK_SETUP_COPY_QUEUE : NULL, FileQ, // callback context NULL, // impersonation callback NULL, // impersonation context &Sxs->Context )) { goto Exit; } // // Set up the reference data to indicate that all of these are OS-installed // assemblies. // ZeroMemory(&InstallReference, sizeof(InstallReference)); InstallReference.cbSize = sizeof(InstallReference); InstallReference.dwFlags = 0; InstallReference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OSINSTALL; // // Let's get the source disk name of this assembly - we'll need it to // pass around as the prompt. // if ( !SetupGetSourceFileLocation( SyssetupInf, NULL, L"shell32.dll", &SourceId, NULL, 0, NULL ) ) goto Exit; if ( !SetupGetSourceInfo( SyssetupInf, SourceId, SRCINFO_DESCRIPTION, DiskNameBuffer, sizeof(DiskNameBuffer), NULL ) ) goto Exit; if (AssembliesRootSource) { // // Set up the structure to call off to the installer // memset(&InstallData, 0, sizeof(InstallData)); InstallData.cbSize = sizeof(InstallData); InstallData.dwFlags = SXS_INSTALL_FLAG_FROM_DIRECTORY | SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE | SXS_INSTALL_FLAG_REFERENCE_VALID | SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID | SXS_INSTALL_FLAG_INSTALL_COOKIE_VALID | SXS_INSTALL_FLAG_INSTALLED_BY_OSSETUP | SXS_INSTALL_FLAG_CODEBASE_URL_VALID; InstallData.lpReference = &InstallReference; InstallData.lpRefreshPrompt = DiskNameBuffer; InstallData.pvInstallCookie = Sxs->Context; InstallData.lpCodebaseURL = AssembliesRootSource; InstallData.lpManifestPath = AssembliesRootSource; if (!Sxs->InstallW(&InstallData)) { // abort call will be made in SideBySideFinish goto Exit; } } else { LineExists = SetupFindFirstLine(SyssetupInf, SXS_INF_ASSEMBLY_DIRECTORIES_SECTION_NAME_W, NULL, &InfContext); while(LineExists) { DWORD FileAttributes = 0; // // convention introduced specifically for side by side, so that // x86 files on ia64 might come from \i386\asms instead of \ia64\asms\i386, // depending on what dosnet.inf and syssetup.inf say: // a path that does not start with a slash is appended to \$win_nt$.~ls\processor; // a path that does start with a slash is appended to \$win_nt$.~ls // InfField = pSetupGetField(&InfContext, 0); if(InfField == NULL) { break; } // c:\$win_nt$.~ls lstrcpyn(AssembliesRootDirectory, SourcePath, MAX_PATH); if (InfField[0] == '\\' || InfField[0] == '/') { InfField += 1; } else { // c:\$win_nt$.~ls\i386 if (!pSetupConcatenatePaths(AssembliesRootDirectory, PlatformName, MAX_PATH, NULL)) { goto Exit; } } // stash this away for a little bit lstrcpyn( PromptForSetupPath, AssembliesRootDirectory, MAX_PATH ); // // For now, while "staging", we allow the directory to not exist, and to be // empty (emptiness is silently handled elsewhere by common code), but // comctl32 will be in an assembly, so assemblies will be mandatory // for the system to boot to Explorer.exe. // // 11/09/2000 (jonwis) If we can't find the assemblies root directory, prompt // for the installation media. This is ripped straight from the headlines // of crypto.c and cmdline.c. // for (;;) { Err = SetupPromptForDisk( MainWindowHandle, // Main window handle NULL, // Dialog title (defaulted) DiskNameBuffer, // Name of the disk to request PromptForSetupPath, // Full path of the asms root InfField, // We look to see if the dir is there NULL, // No tag file IDF_CHECKFIRST | IDF_NOSKIP | IDF_NODETAILS | IDF_NOBROWSE, AssembliesRootDirectoryFound, // What we'll use to install cchAssembliesRootDirectoryFound, // How long is that buffer? NULL ); // See if what we got back from the prompt is success - if so, is the directory // really there? We might assume that it is if we get back _SUCCESS... if ( Err == DPROMPT_SUCCESS ) { FileAttributes = GetFileAttributes(AssembliesRootDirectoryFound); if ((FileAttributes != 0xFFFFFFFF) && (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // copy out the asms directory location that was found, and // stop looking. lstrcpyn(AssembliesRootDirectory, AssembliesRootDirectoryFound, MAX_PATH); break; } } else { break; } }; // c:\$win_nt$.~ls\i386\asms if (!pSetupConcatenatePaths(AssembliesRootDirectory, InfField, MAX_PATH, NULL)) { goto Exit; } // // If we didn't get a success (ie: we broke out of the loop), fail the // installation. Heinous, but MarianT (setup dev) suggests this is the // best method. // if ( Err != DPROMPT_SUCCESS ) goto Exit; // // Set up this structure to call off into SXS to do the installation // for us. // ZeroMemory(&InstallData, sizeof(InstallData)); InstallData.cbSize = sizeof(InstallData); InstallData.dwFlags = SXS_INSTALL_FLAG_FROM_DIRECTORY | SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE | SXS_INSTALL_FLAG_REFERENCE_VALID | SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID | SXS_INSTALL_FLAG_INSTALL_COOKIE_VALID | SXS_INSTALL_FLAG_INSTALLED_BY_OSSETUP | SXS_INSTALL_FLAG_CODEBASE_URL_VALID; InstallData.lpManifestPath = AssembliesRootDirectory; InstallData.lpReference = &InstallReference; InstallData.lpRefreshPrompt = DiskNameBuffer; InstallData.pvInstallCookie = Sxs->Context; InstallData.lpCodebaseURL = SourcePath; if (!Sxs->InstallW( &InstallData )) { // abort call will be made in SideBySideFinish goto Exit; } LineExists = SetupFindNextLine(&InfContext, &InfContext); } } Success = TRUE; Exit: return Success; } BOOL SideBySideFinish( SIDE_BY_SIDE* Sxs, BOOL fSuccess ) { #define FUNCTION L"SideBySideFinish" DWORD dwLastError = NO_ERROR; ASSERT(Sxs != NULL); // // failure to load the .dll or get entry points implies lack of success // ASSERT(Sxs->Dll != NULL || !fSuccess); ASSERT(Sxs->EndAssemblyInstall != NULL || !fSuccess); if (!fSuccess) { dwLastError = GetLastError(); } if (Sxs->Context != NULL) { if (Sxs->EndAssemblyInstall != NULL) { if (!Sxs->EndAssemblyInstall( Sxs->Context, fSuccess ? SXS_END_ASSEMBLY_INSTALL_FLAG_COMMIT : SXS_END_ASSEMBLY_INSTALL_FLAG_ABORT, NULL // reserved out DWORD )) { if (fSuccess) { fSuccess = FALSE; dwLastError = GetLastError(); } } } Sxs->Context = NULL; } if (Sxs->Dll != NULL) { if (!FreeLibrary(Sxs->Dll)) { if (fSuccess) { fSuccess = FALSE; dwLastError = GetLastError(); } } Sxs->Dll = NULL; } if (!fSuccess) { SetLastError(dwLastError); } return fSuccess; #undef FUNCTION } BOOL SideBySideCreateSyssetupContext( VOID ) { #define FUNCTION L"SideBySideCreateSyssetupContext" BOOL fSuccess = FALSE; const PPEB Peb = NtCurrentPeb(); ACTCTXW CreateActCtxParams; HANDLE ActCtxHandle; ASSERT(Peb->ActivationContextData == NULL); ASSERT(Peb->ProcessAssemblyStorageMap == NULL); ASSERT(Peb->SystemAssemblyStorageMap == NULL); CreateActCtxParams.cbSize = sizeof(CreateActCtxParams); CreateActCtxParams.dwFlags = (ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_SET_PROCESS_DEFAULT); CreateActCtxParams.lpResourceName = SXS_MANIFEST_RESOURCE_ID; ASSERT(MyModuleFileName[0] != 0); CreateActCtxParams.lpSource = MyModuleFileName; // // The error value is INVALID_HANDLE_VALUE. // ACTCTX_FLAG_SET_PROCESS_DEFAULT has nothing to return upon success, so it returns NULL. // There is nothing to cleanup upon ACTCTX_FLAG_SET_PROCESS_DEFAULT success, the data // is referenced in the PEB, and lasts till process shutdown. // ActCtxHandle = CreateActCtxW(&CreateActCtxParams); if (ActCtxHandle == INVALID_HANDLE_VALUE) { fSuccess = FALSE; SetupDebugPrint1(L"SETUP: CreateActCtxW failed in " FUNCTION L", LastError is %d\n", GetLastError()); goto Exit; } ASSERT(ActCtxHandle == NULL); fSuccess = TRUE; Exit: return fSuccess; #undef FUNCTION } BOOL CopySystemFiles( VOID ) { BOOL b; HINF hInf; HSPFILEQ FileQ; PVOID Context; WCHAR Dir[MAX_PATH]; DWORD ScanQueueResult; b = FALSE; //hInf = SetupOpenInfFile(L"filelist.inf",NULL,INF_STYLE_WIN4,NULL); hInf = SyssetupInf; if(hInf != INVALID_HANDLE_VALUE) { FileQ = SetupOpenFileQueue(); if(FileQ != INVALID_HANDLE_VALUE) { b = SetupInstallFilesFromInfSection( SyssetupInf, NULL, FileQ, Win31Upgrade ? L"Files.Install.CleanInstall.Win31" : L"Files.Install.CleanInstall", NULL, BaseCopyStyle ); // // Do the installation of class installers // We do this here because the installation of class intallers may involve // file copy. And in this case we can use the existing progress bar. // InstallPnpClassInstallers( MainWindowHandle, hInf, FileQ ); #if 0 // // This feature is going away, because we're going to // build the delete file list using rules // if(Win95Upgrade) { b = b && SetupQueueDeleteSectionW( FileQ, hInf, 0, L"Files.DeleteWin9x.System" ); b = b && SetupQueueDeleteSectionW( FileQ, hInf, 0, L"Files.DeleteWin9x.Sysroot" ); } #endif if(b) { b = FALSE; if(Context = InitSysSetupQueueCallbackEx(MainWindowHandle, INVALID_HANDLE_VALUE,0,0,NULL)) { if(!SetupScanFileQueue( FileQ, SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE, MainWindowHandle, 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(MainWindowHandle,FileQ,SysSetupQueueCallback,Context); } TermSysSetupQueueCallback(Context); } } SetupCloseFileQueue(FileQ); } //SetupCloseInfFile(hInf); } return(b); } BOOL UpgradeSystemFiles( VOID ) { BOOL b; HINF hInf; HSPFILEQ FileQ; PVOID Context; WCHAR Dir[MAX_PATH]; DWORD ScanQueueResult; b = FALSE; //hInf = SetupOpenInfFile(L"filelist.inf",NULL,INF_STYLE_WIN4,NULL); hInf = SyssetupInf; if(hInf != INVALID_HANDLE_VALUE) { FileQ = SetupOpenFileQueue(); if(FileQ != INVALID_HANDLE_VALUE) { b = SetupInstallFilesFromInfSection( SyssetupInf, NULL, FileQ, Win31Upgrade ? L"Files.Install.Upgrade.Win31" : L"Files.Install.Upgrade", NULL, BaseCopyStyle ); // // Do the installation of class installers // We do this here because the installation of class intallers may involve // file copy. And in this case we can use the existing progress bar. // InstallPnpClassInstallers( MainWindowHandle, hInf, FileQ ); if(b) { b = FALSE; if(Context = InitSysSetupQueueCallbackEx(MainWindowHandle, INVALID_HANDLE_VALUE,0,0,NULL)) { if(!SetupScanFileQueue( FileQ, SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE, MainWindowHandle, 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(MainWindowHandle,FileQ,SysSetupQueueCallback,Context); } TermSysSetupQueueCallback(Context); } } SetupCloseFileQueue(FileQ); } //SetupCloseInfFile(hInf); } return(b); } VOID MarkFilesReadOnly( VOID ) { WCHAR OldCurrentDir[MAX_PATH]; WCHAR System32Dir[MAX_PATH]; LPCTSTR SectionName; LONG LineCount; LONG ItemNo; INFCONTEXT InfContext; BOOL b; ASSERT( SyssetupInf != INVALID_HANDLE_VALUE ); // // Set current directory to system32. // Preserve current directory to minimize side-effects. // if(!GetCurrentDirectory(MAX_PATH,OldCurrentDir)) { OldCurrentDir[0] = 0; } GetSystemDirectory(System32Dir,MAX_PATH); SetCurrentDirectory(System32Dir); // // Now go through the list of files. // SectionName = L"Files.MarkReadOnly"; LineCount = SetupGetLineCount( SyssetupInf, SectionName ); for( ItemNo=0; ItemNo