Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

527 lines
16 KiB

/*++
Copyright (c) 1987-1993 Microsoft Corporation
Module Name:
config.c
Abstract:
Creates config table. Parses old style RPLMGR.INI config records
and creates corresponding entries in jet database table.
Author:
Vladimir Z. Vulovic (vladimv) 19 - November - 1993
Revision History:
--*/
#include "local.h"
#define RPLCONFIG_ALLOCATE
#include "config.h"
#undef RPLCONFIG_ALLOCATE
PWCHAR RplmgrIniFile = L"rplmgr.ini";
#define MAX_RPLMGR_INI_FILE_SIZE 0xFFFF // BUGBUG some arbitrary value
#define NO_SCRIPT_FIELDS 13
#define SECTION_STARTMARK L'['
#define CONFIG_BEGIN L"[configuration]"
#define CARRIAGE_RETURN_CHAR L'\r' // 0xD or \015
// #define RPL_DEBUG_ALL
BOOL GetConfigFieldValue(
IN PWCHAR Cursor,
IN DWORD Index
)
/*++
Fields with multiple field values, such as AdapterName, are
not properly parsed here. Howerever, we do not care about
the values of these fields.
--*/
{
PWCHAR End;
DWORD Length;
//
// By default the field is empty.
//
ConfigParseTable[ Index].Value = NULL;
ConfigParseTable[ Index].Size = 0;
//
// Read to EQUALS_CHAR
//
while ( *Cursor != EQUALS_CHAR && *Cursor != COMMENT_CHAR &&
*Cursor != CARRIAGE_RETURN_CHAR) {
Cursor++;
}
if ( *Cursor == COMMENT_CHAR || *Cursor == CARRIAGE_RETURN_CHAR) {
return( TRUE);
}
Cursor++; // Skip EQUALS_CHAR
//
// Read to the beginning of field value.
//
while( *Cursor != CARRIAGE_RETURN_CHAR && iswspace(*Cursor) &&
*Cursor != COMMENT_CHAR) {
Cursor++;
}
if ( *Cursor == COMMENT_CHAR || *Cursor == CARRIAGE_RETURN_CHAR) {
return( TRUE);
}
//
// Make sure that boot block reference is enabled.
//
if ( Index == CONFIG_BootName) {
if ( *Cursor != L'R') {
RplAssert( TRUE, ("Bad boot block id: %.40ws", Cursor));
return( FALSE);
}
Cursor++; // skip leading 'R' in boot block name
}
//
// Find the end point of this field. Since comments may contain spaces,
// space is not used as a separator for CONFIG_ConfigComment field.
//
End = wcspbrk( Cursor, Index == CONFIG_ConfigComment ? L"\f\n\r\t\v" : L" \f\n\r\t\v");
if ( End != NULL) {
Length = End - Cursor;
} else {
Length = wcslen( Cursor);
}
ConfigParseTable[ Index].Value = GlobalAlloc( GMEM_FIXED, (Length+1)*sizeof(WCHAR));
if ( ConfigParseTable[ Index].Value == NULL) {
DWORD Error = GetLastError();
RplAssert( TRUE, ("GlobalAlloc: Error = %d", Error));
return( FALSE);
}
ConfigParseTable[ Index].Size = (Length+1)*sizeof(WCHAR);
memcpy( ConfigParseTable[ Index].Value, Cursor, Length * sizeof(WCHAR));
((PWCHAR)ConfigParseTable[ Index].Value)[ Length] = 0;
return( TRUE);
}
BOOL StringISpaceEqual( IN PWCHAR str1, IN PWCHAR str2 )
/*++
Routine Description:
Case insensitive version of StringsSpaceEqual.
Arguments:
str1 - first string
str2 - second string
Return Value:
TRUE if strings are equal, FALSE otherwise.
--*/
{
WCHAR ch1;
#ifdef NOT_YET
if ( str1 == NULL || str2 == NULL) {
str1 = (str1 != NULL) ? str1 : str2;
if ( str2 == NULL) {
return( TRUE); // both strings are NULL
}
while ( iswspace( *str1++)) {
NOTHING; // check if not NULL string contains spaces only
}
return( *str1 == 0);
}
#endif // NOT_YET
//
// Compare strings until the first space or NULL character
// (in the first string) or until we find the first different character.
//
while ( (ch1 = toupper(*str1)) && !iswspace(ch1) && ch1 == toupper(*str2)) {
str1++, str2++;
}
//
// For strings to be equal, both characters must be NULL or space.
//
if ( (!ch1 || iswspace(ch1)) && (!(ch1 = *str2) || iswspace(ch1)))
{
return( TRUE);
}
return( FALSE);
}
#ifdef RPL_DEBUG_ALL
VOID ProcessConfigDisplay( VOID)
{
DWORD Index;
printf( "\tCONFIGURATION\n");
for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++) {
if ( ConfigParseTable[ Index].Name == NULL) {
continue;
}
printf( "%ws %ws 0x%x\n", ConfigParseTable[ Index].Name,
ConfigParseTable[ Index].Value, ConfigParseTable[ Index].Size);
}
}
#endif
PWCHAR ProcessConfig( IN PWCHAR Cursor)
/*++
Routine Description:
We read all the fields in the Config[] array, then use jet apis
to store this config in the database.
Arguments:
Cursor - at entry this points to the beginning of the config section
Return Value:
Cursor value after we finished processing the current config section.
--*/
{
#define INVALID_ERROR_PARAMETER ((DWORD)(-1))
DWORD Index;
JET_ERR JetError;
DWORD Flags;
DWORD Offset;
DWORD ErrorParameter;
for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++) {
if ( ConfigParseTable[ Index].Value != NULL) {
GlobalFree( ConfigParseTable[ Index].Value);
}
ConfigParseTable[ Index].Value = NULL;
}
if ( OffsetAfterComment( Cursor) == 0) {
Flags = CONFIG_FLAGS_ENABLED_TRUE;
} else {
Flags = CONFIG_FLAGS_ENABLED_FALSE;
}
for ( Cursor=GetNextLine(Cursor), ErrorParameter = INVALID_ERROR_PARAMETER;
*Cursor!=0; Cursor=GetNextLine(Cursor)) {
Offset = OffsetAfterComment( Cursor);
if ( *(Cursor+Offset) == SECTION_STARTMARK) {
break; // start of a new section, write the current section
}
Cursor += Offset;
//
// Find value for this name.
//
for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++) {
if ( ConfigParseTable[ Index].Name == NULL) {
continue; // skip this one, not a RPLMGR.INI keyword
}
if ( !StringISpaceEqual( Cursor, ConfigParseTable[ Index].Name)) {
continue; // no match with this keyword
}
if ( !GetConfigFieldValue( Cursor, Index)) {
if ( ErrorParameter == INVALID_ERROR_PARAMETER) {
ErrorParameter = Index;
}
} else if ( Index == CONFIG_FitShared || Index == CONFIG_FitPersonal) {
PWCHAR Value;
Value = AddFileExtension( ConfigParseTable[ Index].Value,
L".FIT", TRUE);
if ( Value == NULL) {
if ( ErrorParameter == INVALID_ERROR_PARAMETER) {
ErrorParameter = Index;
}
} else if ( Value != ConfigParseTable[ Index].Value) {
GlobalFree( ConfigParseTable[ Index].Value);
ConfigParseTable[ Index].Value = Value;
ConfigParseTable[ Index].Size = (wcslen(Value)+1)*sizeof(WCHAR);
}
}
break;
}
}
#ifdef RPL_DEBUG_ALL
ProcessConfigDisplay();
#endif
if ( ConfigParseTable[ CONFIG_ConfigName].Value == NULL) {
RplAssert( TRUE, ("Bad config"));
return( Cursor);
}
//
// Perform same checks as in NetrRplConfigAdd.
//
if ( ErrorParameter != INVALID_ERROR_PARAMETER) {
NOTHING; // do not overwrite the first error
} else if ( !ValidName( ConfigParseTable[ CONFIG_FitPersonal].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
ErrorParameter = CONFIG_FitPersonal;
} else if ( !ValidName( ConfigParseTable[ CONFIG_FitShared].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
ErrorParameter = CONFIG_FitShared;
} else if ( !ValidName( ConfigParseTable[ CONFIG_DirName4].Value, RPL_MAX_STRING_LENGTH, FALSE)) {
ErrorParameter = CONFIG_DirName4;
} else if ( !ValidName( ConfigParseTable[ CONFIG_DirName3].Value, RPL_MAX_STRING_LENGTH, FALSE)) {
ErrorParameter = CONFIG_DirName3;
} else if ( !ValidName( ConfigParseTable[ CONFIG_DirName2].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
ErrorParameter = CONFIG_DirName2;
} else if ( !ValidName( ConfigParseTable[ CONFIG_DirName].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
ErrorParameter = CONFIG_DirName;
} else if ( !ValidName( ConfigParseTable[ CONFIG_BootName].Value, RPL_MAX_BOOT_NAME_LENGTH, TRUE)) {
ErrorParameter = CONFIG_BootName;
} else if ( !ValidName( ConfigParseTable[ CONFIG_ConfigName].Value, RPL_MAX_CONFIG_NAME_LENGTH, TRUE)) {
ErrorParameter = CONFIG_ConfigName;
}
if ( ErrorParameter < CONFIG_TABLE_LENGTH) {
RplPrintf2( RPLI_CVT_ConfigInvalid, ConfigParseTable[ CONFIG_ConfigName].Value, ConfigParseTable[ ErrorParameter].Name);
return( Cursor);
}
if ( ConfigParseTable[ CONFIG_FitPersonal].Value == NULL) {
//
// Ignore default boot configurations.
//
RplPrintf1( RPLI_CVT_ConfigNoPersonalFIT, ConfigParseTable[ CONFIG_ConfigName].Value);
return( Cursor);
}
if ( !_wcsicmp( L"OS2", ConfigParseTable[ CONFIG_DirName].Value )) {
//
// Ignore OS/2 configurations.
//
RplPrintf1( RPLI_CVT_ConfigNoOS2, ConfigParseTable[ CONFIG_ConfigName].Value);
return( Cursor);
}
if ( RPL_STRING_TOO_LONG( ConfigParseTable[ CONFIG_ConfigComment].Value)) {
//
// Silently truncate comments that are too long.
//
((PWCHAR)ConfigParseTable[ CONFIG_ConfigComment].Value)[ RPL_MAX_STRING_LENGTH] = 0;
ConfigParseTable[ CONFIG_ConfigComment].Size = (RPL_MAX_STRING_LENGTH+1)*sizeof(WCHAR);
}
_wcsupr( (PWCHAR)ConfigParseTable[ CONFIG_BootName].Value);
_wcsupr( (PWCHAR)ConfigParseTable[ CONFIG_ConfigName].Value);
Call( JetPrepareUpdate( SesId, ConfigTableId, JET_prepInsert));
for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++ ) {
if ( ConfigParseTable[ Index].Name == NULL) {
continue;
}
JetError = JetSetColumn( SesId, ConfigTableId,
ConfigTable[ Index].ColumnId, ConfigParseTable[ Index].Value,
ConfigParseTable[ Index].Size, 0, NULL);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("Index=%d(dec) JetError=%d", Index, JetError));
}
}
Call( JetSetColumn( SesId, ConfigTableId,
ConfigTable[ CONFIG_Flags].ColumnId, &Flags, sizeof(Flags), 0, NULL));
Call( JetUpdate( SesId, ConfigTableId, NULL, 0, NULL));
return( Cursor);
}
DWORD ProcessRplmgrIni( IN LPWSTR FilePath)
{
PWCHAR Cursor;
PWCHAR String;
JET_COLUMNDEF ColumnDef;
JET_ERR JetError;
DWORD Index;
DWORD Offset;
CHAR IndexKey[ 255];
JetError = JetCreateTable( SesId, DbId, "config", CONFIG_TABLE_PAGE_COUNT,
CONFIG_TABLE_DENSITY, &ConfigTableId);
ColumnDef.cbStruct = sizeof( ColumnDef);
ColumnDef.columnid = 0;
ColumnDef.coltyp = JET_coltypLong;
ColumnDef.cbMax = 0;
ColumnDef.grbit = 0;
//
// Create columns. First initialize fields that do not change between
// addition of columns.
//
ColumnDef.cbStruct = sizeof(ColumnDef);
ColumnDef.columnid = 0;
ColumnDef.wCountry = 1;
ColumnDef.langid = 0x0409; // USA english
ColumnDef.cp = 1200; // UNICODE codepage
ColumnDef.wCollate = 0;
ColumnDef.cbMax = 0;
ColumnDef.grbit = 0; // variable length binary and text data.
for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++ ) {
ColumnDef.coltyp = ConfigTable[ Index].ColumnType;
JetError = JetAddColumn( SesId, ConfigTableId,
ConfigTable[ Index].ColumnName, &ColumnDef,
NULL, 0, &ConfigTable[ Index].ColumnId);
if( JetError != ERROR_SUCCESS ) {
return( MapJetError( JetError));
}
}
Offset = AddKey( IndexKey, '+', ConfigTable[ CONFIG_ConfigName].ColumnName);
IndexKey[ Offset++] = '\0';
JetError = JetCreateIndex( SesId, ConfigTableId, CONFIG_INDEX_ConfigName,
JET_bitIndexPrimary, IndexKey, Offset, 50);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
return( MapJetError( JetError));
}
//
// +BootName+ConfigName index is used to enumerate all configurations for
// a given VendorId.
//
Offset = AddKey( IndexKey, '+', ConfigTable[ CONFIG_BootName].ColumnName);
Offset += AddKey( IndexKey + Offset, '+', ConfigTable[ CONFIG_ConfigName].ColumnName);
IndexKey[ Offset++] = '\0';
JetError = JetCreateIndex( SesId, ConfigTableId, CONFIG_INDEX_BootNameConfigName,
JET_bitIndexUnique, IndexKey, Offset, 50);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
return( MapJetError( JetError));
}
//
// Make config name a current index - used to validate profiles.
//
JetError = JetSetCurrentIndex( SesId, ConfigTableId, CONFIG_INDEX_ConfigName);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("SetCurrentIndex failed err=%d", JetError));
return( MapJetError( JetError));
}
String = ReadTextFile( FilePath, RplmgrIniFile, MAX_RPLMGR_INI_FILE_SIZE);
if ( String == NULL) {
return( GetLastError());
}
//
// If current line is the beginning of configuration, we process
// that configuration (note that this processing has the side effect of
// advancing the cursor), else we just advance the cursor.
//
for ( Cursor = GetFirstLine( String); *Cursor != 0; NOTHING) {
Offset = OffsetAfterComment( Cursor);
if ( StringISpaceEqual( Cursor+Offset, CONFIG_BEGIN)) {
Cursor = ProcessConfig( Cursor);
} else {
Cursor = GetNextLine( Cursor);
}
}
if ( GlobalFree( String) != NULL) {
RplAssert( TRUE, ("GlobalFree: Error=%d", GetLastError()));
}
return( ERROR_SUCCESS);
}
VOID ConfigPruneTable( VOID)
/*++
Eliminate config records that do not have a corresponding
boot block record defined.
--*/
{
WCHAR Name[ 20];
DWORD NameSize;
JET_ERR ForJetError;
JET_ERR JetError;
for ( ForJetError = JetMove( SesId, ConfigTableId, JET_MoveFirst, 0);
ForJetError == JET_errSuccess;
ForJetError = JetMove( SesId, ConfigTableId, JET_MoveNext, 0)) {
JetError = JetRetrieveColumn( SesId, ConfigTableId,
ConfigTable[ CONFIG_BootName].ColumnId, Name,
sizeof( Name), &NameSize, 0, NULL);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
Call( JetDelete( SesId, ConfigTableId));
continue;
}
if ( !FindBoot( Name)) {
#ifdef RPL_DEBUG_ALL
WCHAR Value[ 20];
JetRetrieveColumn( SesId, ConfigTableId,
ConfigTable[ CONFIG_ConfigName].ColumnId, Value,
sizeof( Value), &NameSize, 0, NULL);
printf("Deleting config %ws since boot %ws was not found\n",
Value, Name);
#endif
Call( JetDelete( SesId, ConfigTableId));
continue;
}
}
}
BOOL FindConfig( IN PWCHAR Name)
{
JET_ERR JetError;
JetError = JetMove( SesId, ConfigTableId, JET_MoveFirst, 0);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("JetMove failed err=%d", JetError));
return( FALSE);
}
JetError = JetMakeKey( SesId, ConfigTableId, Name,
( wcslen( Name) + 1) * sizeof(WCHAR), JET_bitNewKey);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("MakeKey failed err=%d", JetError));
return( FALSE);
}
JetError = JetSeek( SesId, ConfigTableId, JET_bitSeekEQ);
if ( JetError != JET_errSuccess) {
RplAssert( TRUE, ("JetSeek for %ws failed err=%d", Name, JetError));
return( FALSE);
}
return( TRUE);
}
VOID ConfigListTable( VOID)
{
ListTable( CONFIG_TABLE_NAME, ConfigTable[ CONFIG_ConfigName].ColumnName,
CONFIG_INDEX_ConfigName);
}