windows-nt/Source/XPSP1/NT/base/ntsetup/syssetup/vdm.c
2020-09-26 16:20:57 +08:00

517 lines
12 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
vdm.c
Abstract:
Routines to configure the MS-DOS subsystem.
Author:
Ted Miller (tedm) 27-Apr-1995
Revision History:
--*/
#include "setupp.h"
#pragma hdrstop
//
// Keywords whose presence in config.sys indicate OS/2.
//
PCSTR Os2ConfigSysKeywords[] = { "DISKCACHE", "LIBPATH", "PAUSEONERROR",
"RMSIZE", "RUN", "SWAPPATH",
"IOPL", "MAXWAIT", "MEMMAN",
"PRIORITY", "PROTSHELL", "PROTECTONLY",
"THREADS", "TIMESLICE", "TRACE",
"TRACEBUF", "DEVINFO", NULL
};
//
// Keywords we migrate from the user's existing DOS config.sys
// into config.nt.
//
#define NUM_DOS_KEYWORDS 4
PCSTR DosConfigSysKeywords[NUM_DOS_KEYWORDS] = { "FCBS","BREAK","LASTDRIVE","FILES" };
BOOL
DosConfigSysExists(
IN PCWSTR Filename
);
BOOL
CreateConfigNt(
IN PCWSTR ConfigDos,
IN PCWSTR ConfigTmp,
IN PCWSTR ConfigNt
);
PSTR
IsolateFirstField(
IN PSTR Line,
OUT PSTR *End,
OUT PCHAR Terminator
);
BOOL
ConfigureMsDosSubsystem(
VOID
)
/*++
Routine Description:
Configure the 16-bit MS-DOS subsystem.
Currently this means creating config.nt and autoexec.nt.
It also means creating empty config.sys, autoexec.bat, io.sys and msdos.sys
if these files don't already exist.
On the upgrade, the only thing that we do is to create the empty files,
if they don't already exist.
Arguments:
None.
Return Value:
Boolean value indicating outcome.
--*/
{
WCHAR ConfigDos[] = L"?:\\CONFIG.SYS";
WCHAR ConfigTmp[MAX_PATH];
WCHAR ConfigNt[MAX_PATH];
WCHAR AutoexecDos[] = L"?:\\AUTOEXEC.BAT";
WCHAR AutoexecTmp[MAX_PATH];
WCHAR AutoexecNt[MAX_PATH];
WCHAR IoSysFile[] = L"?:\\IO.SYS";
WCHAR MsDosSysFile[] = L"?:\\MSDOS.SYS";
WCHAR ControlIniFile[MAX_PATH];
BOOL b;
DWORD Result;
ULONG i;
HANDLE FileHandle;
PWSTR DosFileNames[] = {
ConfigDos,
AutoexecDos,
IoSysFile,
MsDosSysFile,
ControlIniFile
};
DWORD DosFileAttributes[] = {
FILE_ATTRIBUTE_NORMAL,
FILE_ATTRIBUTE_NORMAL,
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY,
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY,
FILE_ATTRIBUTE_NORMAL
};
//
// Fill in drive letter of system partition.
//
#ifdef _X86_
ConfigDos[0] = x86SystemPartitionDrive;
AutoexecDos[0] = x86SystemPartitionDrive;
IoSysFile[0] = x86SystemPartitionDrive;
MsDosSysFile[0] = x86SystemPartitionDrive;
#else
ConfigDos[0] = L'C';
AutoexecDos[0] = L'C';
IoSysFile[0] = L'C';
MsDosSysFile[0] = L'C';
#endif
//
// Build path to control.ini file
//
Result = GetWindowsDirectory(ControlIniFile,MAX_PATH);
if( Result == 0) {
MYASSERT(FALSE);
return FALSE;
}
pSetupConcatenatePaths(ControlIniFile,L"control.ini",MAX_PATH,NULL);
//
// Create empty config.sys, autoexec.bat, io.sys, msdos.sys and control.ini
// if they don't exist. This is because some 16-bit apps depend on
// these files and SudeepB wants this moved from VDM to setup.
//
for( i = 0; i < sizeof( DosFileNames ) / sizeof( PWSTR ); i++ ) {
FileHandle = CreateFile( DosFileNames[i],
GENERIC_READ | GENERIC_WRITE,
0, // File is not to be shared
NULL, // No security attributes
CREATE_NEW, // Create only if it doesn't exist
DosFileAttributes[i],
NULL ); // No extended attributes
if( FileHandle != INVALID_HANDLE_VALUE ) {
CloseHandle( FileHandle );
}
}
if( Upgrade ) {
return( TRUE );
}
//
// Form filenames.
//
GetSystemDirectory(ConfigTmp,MAX_PATH);
lstrcpy(ConfigNt,ConfigTmp);
lstrcpy(AutoexecNt,ConfigTmp);
lstrcpy(AutoexecTmp,ConfigTmp);
pSetupConcatenatePaths(ConfigTmp,L"CONFIG.TMP",MAX_PATH,NULL);
pSetupConcatenatePaths(ConfigNt,L"CONFIG.NT",MAX_PATH,NULL);
pSetupConcatenatePaths(AutoexecTmp,L"AUTOEXEC.TMP",MAX_PATH,NULL);
pSetupConcatenatePaths(AutoexecNt,L"AUTOEXEC.NT",MAX_PATH,NULL);
//
// If the temp files don't exist, we're done.
// If they do, set their attributes so that we can delete them later.
//
if(!FileExists(ConfigTmp,NULL) || !FileExists(AutoexecTmp,NULL)) {
return(TRUE);
}
SetFileAttributes(ConfigTmp,FILE_ATTRIBUTE_NORMAL);
SetFileAttributes(AutoexecTmp,FILE_ATTRIBUTE_NORMAL);
//
// Get rid of any existing nt config files. We don't support
// merging/upgrading them; we support only ooverwriting them.
//
SetFileAttributes(ConfigNt,FILE_ATTRIBUTE_NORMAL);
SetFileAttributes(AutoexecNt,FILE_ATTRIBUTE_NORMAL);
DeleteFile(ConfigNt);
DeleteFile(AutoexecNt);
//
// If a DOS config.sys exists, merge the template config.sys
// and the dos config.sys to form the nt config.sys.
// Otherwise move the config.sys template over to be the
// nt config file.
//
if(DosConfigSysExists(ConfigDos)) {
b = CreateConfigNt(ConfigDos,ConfigTmp,ConfigNt);
} else {
b = MoveFile(ConfigTmp,ConfigNt);
}
//
// We don't do anything special with autoexec.bat.
// Just move the template over to be the nt file.
//
if(!MoveFile(AutoexecTmp,AutoexecNt)) {
b = FALSE;
}
return(b);
}
BOOL
DosConfigSysExists(
IN PCWSTR Filename
)
/*++
Routine Description:
Determine whether a given file is a DOS config.sys.
Arguments:
Filename - supplies name of file to check.
Return Value:
TRUE if the file exists and is not an OS/2 config.sys.
FALSE if the file does not exist or is an OS/2 config.sys.
--*/
{
BOOL b;
FILE *f;
CHAR Line[512];
UINT i;
PCHAR p;
CHAR c;
PSTR End;
PSTR filename;
filename = pSetupUnicodeToAnsi(Filename);
if(!filename) {
return(FALSE);
}
b = FALSE;
if(FileExists(Filename,NULL)) {
b = TRUE;
if(f = fopen(filename,"rt")) {
while(b && fgets(Line,sizeof(Line),f)) {
if(p = IsolateFirstField(Line,&End,&c)) {
for(i=0; b && Os2ConfigSysKeywords[i]; i++) {
if(!lstrcmpiA(p,Os2ConfigSysKeywords[i])) {
b = FALSE;
}
}
}
}
fclose(f);
}
}
MyFree(filename);
return(b);
}
BOOL
CreateConfigNt(
IN PCWSTR ConfigDos,
IN PCWSTR ConfigTmp,
IN PCWSTR ConfigNt
)
/*++
Routine Description:
Create config.nt. This is done by merging config.tmp (copied during setup)
and the user's existing DOS config.sys. We migrate certain lines from
the DOS config.sys into config.nt.
Arguments:
ConfigDos - supplies filename of DOS config.sys.
ConfigTmp - supplies filename of template config.sys.
ConfigNt - supplies filename of config.nt to be created.
Return Value:
Boolean value indicating outcome.
--*/
{
FILE *DosFile;
FILE *NtFile;
FILE *TmpFile;
BOOL b;
CHAR Line[512];
PCHAR p;
BOOL Found;
BOOL SawKeyword[NUM_DOS_KEYWORDS];
PCSTR FoundKeyword[NUM_DOS_KEYWORDS];
PSTR FoundLine[NUM_DOS_KEYWORDS];
UINT KeywordsFound;
CHAR c;
PSTR End;
PCSTR configDos,configTmp,configNt;
UINT i;
//
// Open the dos file for reading.
// Create the nt file for writing.
// Open the template file for reading.
//
b = FALSE;
if(configDos = pSetupUnicodeToAnsi(ConfigDos)) {
DosFile = fopen(configDos,"rt");
MyFree(configDos);
if(!DosFile) {
goto err0;
}
} else {
goto err0;
}
if(configNt = pSetupUnicodeToAnsi(ConfigNt)) {
NtFile = fopen(configNt,"wt");
MyFree(configNt);
if(!NtFile) {
goto err1;
}
} else {
goto err1;
}
if(configTmp = pSetupUnicodeToAnsi(ConfigTmp)) {
TmpFile = fopen(configTmp,"rt");
MyFree(configTmp);
if(!TmpFile) {
goto err2;
}
} else {
goto err2;
}
//
// Process the DOS file. Read each line and see if it's one
// we care about. If so, save it for later.
//
ZeroMemory(SawKeyword,sizeof(SawKeyword));
KeywordsFound = 0;
while(fgets(Line,sizeof(Line),DosFile)) {
//
// Isolate the first field.
//
if(p = IsolateFirstField(Line,&End,&c)) {
//
// See if we care about this line.
//
for(i=0; i<NUM_DOS_KEYWORDS; i++) {
if(!SawKeyword[i] && !lstrcmpiA(p,DosConfigSysKeywords[i])) {
//
// Remember that we saw this line and save away
// the rest of the line for later.
//
*End = c;
SawKeyword[i] = TRUE;
FoundKeyword[KeywordsFound] = DosConfigSysKeywords[i];
FoundLine[KeywordsFound] = MyMalloc(lstrlenA(p)+1);
if(!FoundLine[KeywordsFound]) {
goto err3;
}
lstrcpyA(FoundLine[KeywordsFound],p);
KeywordsFound++;
break;
}
}
}
}
//
// Look at each line in the template file.
// If it's a line with a value we respect, make sure the line
// does not exist in the DOS file. If it exists in the DOS file
// use the DOS value instead.
//
while(fgets(Line,sizeof(Line),TmpFile)) {
//
// Isolate the first field in the template line and
// check against those we found in the DOS file.
//
Found = FALSE;
if(p = IsolateFirstField(Line,&End,&c)) {
for(i=0; i<KeywordsFound; i++) {
if(!lstrcmpiA(FoundKeyword[i],p)) {
Found = TRUE;
break;
}
}
}
*End = c;
if(Found) {
//
// Use value we found in the dos file.
//
fputs(FoundLine[i],NtFile);
} else {
//
// Use line from template file as-is.
//
fputs(Line,NtFile);
}
}
b = TRUE;
err3:
for(i=0; i<KeywordsFound; i++) {
MyFree(FoundLine[i]);
}
fclose(TmpFile);
err2:
fclose(NtFile);
err1:
fclose(DosFile);
err0:
return(b);
}
PSTR
IsolateFirstField(
IN PSTR Line,
OUT PSTR *End,
OUT PCHAR Terminator
)
/*++
Routine Description:
Isolate the first token in a line of config.sys. The first field
starts at the first non-space/tab character, and is terminated
by a space/tab, newline, or equals.
Arguments:
Line - supplies pointer to line whose first field is desired.
End - receives a pointer to the character that termianted the first
field. That character will have been overwritten with a nul byte.
Terminator - receives the character that terminated the first field,
before we overwrote it with a nul byte.
Return Value:
Pointer to the first field. If the line is blank, the return value
will be NULL.
--*/
{
PSTR p,q;
//
// Get start of first field.
//
p = Line;
while((*p == ' ') || (*p == '\t')) {
p++;
}
//
// If line is empty or bogus, we're done.
//
if((*p == 0) || (*p == '\r') || (*p == '\n') || (*p == '=')) {
return(NULL);
}
//
// Find end of field.
//
q = p;
while(*q && !strchr("\r\n \t=",*q)) {
q++;
}
*End = q;
*Terminator = *q;
*q = 0;
return(p);
}