Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1015 lines
31 KiB

//----------------------------------------------------------------------------
//
// Copyright (c) 1997-1999 Microsoft Corporation
// All rights reserved.
//
// File Name:
// init.c
//
// Description: This file contains all of the functions that handle
// initialization of the App.
//
//----------------------------------------------------------------------------
#include "pch.h"
#include "allres.h"
//
// Net support
//
static VOID
LoadStringsAndDefaultsForNetworkComponents( VOID);
//
// Timezone support
//
static BOOL ReadZoneData(TIME_ZONE_ENTRY* zone, HKEY key);
static TIME_ZONE_LIST *BuildTimeZoneList(VOID);
//
// Regional Settings support
//
static VOID BuildLanguageLists( VOID );
extern BOOL GetCommaDelimitedEntry( OUT TCHAR szString[],
IN OUT TCHAR **pBuffer );
//----------------------------------------------------------------------------
//
// Function: InitTheWizard
//
// Purpose: Performs one time initialization for the App. This function
// is to be called once and only once each time the App is run.
//
// Arguments: VOID
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID InitTheWizard(VOID) {
//
// Save the dir the program was launched from
//
GetCurrentDirectory( MAX_PATH + 1, FixedGlobals.szSavePath );
//
// Have to load the strings for the titles on the networking property
// sheets here because the title is displayed before the WM_INITDIALOG
// message is sent
//
g_StrTcpipTitle = MyLoadString( IDS_TCPIP_TITLE );
g_StrAdvancedTcpipSettings = MyLoadString( IDS_ADVANCED_TCPIP_SETTINGS );
g_StrIpxProtocolTitle = MyLoadString( IDS_IPX_PROTOCOL_TITLE );
g_StrAppletalkProtocolTitle = MyLoadString( IDS_APPLETALK_TITLE );
g_StrMsClientTitle = MyLoadString( IDS_MSCLIENT_TITLE );
//
// Initialize network settings
//
NetSettings.NetworkAdapterHead = malloc( sizeof( NETWORK_ADAPTER_NODE ) );
NetSettings.pCurrentAdapter = NetSettings.NetworkAdapterHead;
CreateListWithDefaults( NetSettings.pCurrentAdapter );
//
// Initialize the number of network card variables
//
NetSettings.iNumberOfNetworkCards = 1;
NetSettings.iCurrentNetworkCard = 1;
NetSettings.NetworkAdapterHead->next = NULL;
LoadStringsAndDefaultsForNetworkComponents();
//
// Build the list of timezones
//
FixedGlobals.TimeZoneList = BuildTimeZoneList();
//
// Build the list of Language Groups and Locales
//
BuildLanguageLists();
}
//--------------------------------------------------------------------------
//
// Support for loading timezone info from the registry
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Function: ReadZoneData
//
// Purpose: Fills in a TIME_ZONE_ENTRY.
//
// Returns: BOOL
//
//--------------------------------------------------------------------------
static BOOL ReadZoneData(TIME_ZONE_ENTRY* zone, HKEY key)
{
DWORD len;
//
// Get the display name
//
len = sizeof(zone->DisplayName);
if ( RegQueryValueEx(key,
REGVAL_TZ_DISPLAY,
0,
NULL,
(LPBYTE)zone->DisplayName,
&len) != ERROR_SUCCESS ) {
return (FALSE);
}
//
// Get the StandardName
//
len = sizeof(zone->StdName);
if ( RegQueryValueEx(key,
REGVAL_TZ_STDNAME,
0,
NULL,
(LPBYTE)zone->StdName,
&len) != ERROR_SUCCESS ) {
return (FALSE);
}
//
// Get the number associatted with this timezone
//
zone->Index = 0;
len = sizeof(zone->Index);
if ( RegQueryValueEx(key,
REGVAL_TZ_INDEX,
0,
NULL,
(LPBYTE)&zone->Index,
&len) != ERROR_SUCCESS ) {
return (FALSE);
}
return (TRUE);
}
//----------------------------------------------------------------------------
//
// Function: InsertZone
//
// Purpose: Inserts a timezone entry into the timezone list maintains a sorted
// order.
//
// Arguments: IN OUT TIME_ZONE_LIST *TzList - time zone list the entry is to
// be inserted to
// IN TIME_ZONE_ENTRY NewTimeZoneEntry - the timezone entry to be
// inserted
// IN INT iNumberOfZonesInserted - number of timezone entries
// already inserted in to the TzList
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
InsertZone( IN OUT TIME_ZONE_LIST *TzList,
IN TIME_ZONE_ENTRY NewTimeZoneEntry,
IN INT iNumberOfZonesInserted ) {
INT i = 0;
INT j;
while( i < iNumberOfZonesInserted ) {
if( TzList->TimeZones[i].Index < NewTimeZoneEntry.Index ) {
i++;
}
else {
break; // we found the insertion point
}
}
//
// Slide all the entries up 1 to make room for the new entry
//
for( j = iNumberOfZonesInserted - 1; j >= i; j-- ) {
lstrcpyn( TzList->TimeZones[j+1].DisplayName,
TzList->TimeZones[j].DisplayName, AS(TzList->TimeZones[j+1].DisplayName) );
lstrcpyn( TzList->TimeZones[j+1].StdName,
TzList->TimeZones[j].StdName, AS(TzList->TimeZones[j+1].StdName) );
TzList->TimeZones[j+1].Index = TzList->TimeZones[j].Index;
}
//
// Add the new entry to the array
//
lstrcpyn( TzList->TimeZones[i].DisplayName, NewTimeZoneEntry.DisplayName, AS(TzList->TimeZones[i].DisplayName) );
lstrcpyn( TzList->TimeZones[i].StdName, NewTimeZoneEntry.StdName, AS(TzList->TimeZones[i].StdName) );
TzList->TimeZones[i].Index = NewTimeZoneEntry.Index;
}
//--------------------------------------------------------------------------
//
// Function: BuildTimeZoneList
//
// Purpose: Mallocs and fills in a TIME_ZONE_LIST which has an array of
// timezone data.
//
// Returns: BOOL - success
//
//--------------------------------------------------------------------------
static TIME_ZONE_LIST *BuildTimeZoneList(VOID)
{
HKEY TimeZoneRootKey = NULL;
WCHAR SubKeyName[TZNAME_SIZE];
HKEY SubKey = NULL;
int i;
INT iNumberOfZonesInserted;
TIME_ZONE_ENTRY TempTimeZoneEntry;
DWORD NumTimeZones = 0;
TIME_ZONE_LIST *TzList;
TCHAR *szTempString;
//
// Open the root of the timezone list in the registry.
//
if (RegOpenKey( HKEY_LOCAL_MACHINE,
REGKEY_TIMEZONES,
&TimeZoneRootKey ) != ERROR_SUCCESS) {
return NULL;
}
//
// Find out how many sub-keys (timezones) there are.
//
RegQueryInfoKey(TimeZoneRootKey,
NULL,
NULL,
NULL,
&NumTimeZones,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
//
// We need to fudge the number of TIME_ZONE_ENTRIES because we add
// 2 special ones "Set Same As Server" and "Do Not Specify".
//
NumTimeZones += 2;
//
// Malloc the memory we need
//
if ( (TzList = malloc(sizeof(TIME_ZONE_LIST))) == NULL ) {
RegCloseKey(TimeZoneRootKey);
return NULL;
}
TzList->NumEntries = NumTimeZones;
TzList->TimeZones = malloc(NumTimeZones * sizeof(TIME_ZONE_ENTRY));
if ( TzList->TimeZones == NULL ) {
RegCloseKey(TimeZoneRootKey);
free(TzList);
return NULL;
}
//
// Enumerate the sub-keys under the timezone root. Each key at this
// level is the standard name of a timezone. Under that key are
// the values we care about. Call ReadZoneData() for each one to
// retrieve the display name and index.
//
i = 0;
iNumberOfZonesInserted = 0;
while ( RegEnumKey(TimeZoneRootKey,
i,
SubKeyName,
TZNAME_SIZE) == ERROR_SUCCESS) {
if (RegOpenKey(TimeZoneRootKey,
SubKeyName,
&SubKey) == ERROR_SUCCESS) {
if ( ReadZoneData( &TempTimeZoneEntry, SubKey) ) {
InsertZone( TzList,
TempTimeZoneEntry,
iNumberOfZonesInserted );
iNumberOfZonesInserted++;
}
}
RegCloseKey(SubKey);
i++;
}
RegCloseKey(TimeZoneRootKey);
//
// Put the 2 special entries in at the end of the list
//
szTempString = MyLoadString(IDS_DONTSPECIFYSETTING);
if (szTempString == NULL)
{
free(TzList->TimeZones);
free(TzList);
return NULL;
}
lstrcpyn(TzList->TimeZones[NumTimeZones-2].DisplayName, szTempString, AS(TzList->TimeZones[NumTimeZones-2].DisplayName));
lstrcpyn(TzList->TimeZones[NumTimeZones-2].StdName, _T(""), AS(TzList->TimeZones[NumTimeZones-2].StdName));
TzList->TimeZones[NumTimeZones-2].Index = TZ_IDX_DONOTSPECIFY;
free( szTempString );
szTempString = MyLoadString(IDS_SET_SAME_AS_SERVER);
if (szTempString == NULL)
{
free(TzList->TimeZones);
free(TzList);
return NULL;
}
lstrcpyn(TzList->TimeZones[NumTimeZones-1].DisplayName, szTempString, AS(TzList->TimeZones[NumTimeZones-1].DisplayName));
lstrcpyn(TzList->TimeZones[NumTimeZones-1].StdName, _T(""), AS(TzList->TimeZones[NumTimeZones-1].StdName));
TzList->TimeZones[NumTimeZones-1].Index = TZ_IDX_SETSAMEASSERVER;
free(szTempString);
//
// Add in the 2 special strings
//
iNumberOfZonesInserted = iNumberOfZonesInserted + 2;
if ( iNumberOfZonesInserted != (int) NumTimeZones ) {
free(TzList->TimeZones);
free(TzList);
return NULL;
}
return TzList;
}
//----------------------------------------------------------------------------
//
// Function: ReadAllFilesUnderSection
//
// Purpose:
//
// Arguments:
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID
ReadAllFilesUnderSection( IN HINF hInterntlInf,
IN LPCTSTR pszSubSectionName,
OUT NAMELIST *CurrentNameList )
{
TCHAR szLangFileName[MAX_PATH + 1];
INFCONTEXT LangInfContext = { 0 };
INT iRet;
AssertMsg( hInterntlInf != INVALID_HANDLE_VALUE,
"Bad handle" );
AssertMsg( GetNameListSize( CurrentNameList ) < 100,
"Too many entries" );
iRet = SetupFindFirstLine( hInterntlInf, pszSubSectionName, NULL, &LangInfContext );
if( iRet == 0 )
{
//
// If the subsection can't be found, just return. When this happens, it
// mostly likely means there are no files under this subsection.
//
return;
}
do {
szLangFileName[0] = _T('\0');
iRet = SetupGetStringField( &LangInfContext,
1,
szLangFileName,
MAX_PATH,
NULL );
if( iRet == 0 )
{
//
// If a file cannot be obtained, move on to the next one.
//
continue;
}
if( szLangFileName[0] != _T('\0') )
{
AddNameToNameListNoDuplicates( CurrentNameList,
szLangFileName );
}
} // move to the next line of the .inf file
while( SetupFindNextLine( &LangInfContext, &LangInfContext ) );
}
//----------------------------------------------------------------------------
//
// Function: BuildAdditionalLanguageList
//
// Purpose: Populate the LangGroupAdditionalFiles array
//
// LangGroupAdditionalFiles is a dynamically allocated array of Namelists
// that contain the extra files in the intl.inf that need to be copied for
// a language group in addition to its sub-directory.
//
// Arguments:
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID
BuildAdditionalLanguageList( IN HINF hInterntlInf, IN const INT iLangGroupCount )
{
INT i;
INT j;
INT iRetVal;
INT iSubSectionEntries;
TCHAR szBuffer[MAX_INILINE_LEN];
TCHAR szIniBuffer[MAX_INILINE_LEN];
TCHAR szSectionName[MAX_INILINE_LEN];
TCHAR szIntlInf[MAX_PATH + 1];
TCHAR *pszSubSectionName;
TCHAR *pszIniBuffer;
NAMELIST SubSectionList = { 0 };
HRESULT hrCat;
AssertMsg( hInterntlInf != INVALID_HANDLE_VALUE,
"Bad handle" );
iRetVal = GetWindowsDirectory( szIntlInf, MAX_PATH );
if( iRetVal == 0 || iRetVal > MAX_PATH )
{
return;
}
hrCat=StringCchCat( szIntlInf, AS(szIntlInf), _T("\\inf\\intl.inf") );
FixedGlobals.LangGroupAdditionalFiles = malloc( sizeof(NAMELIST) * iLangGroupCount );
if (FixedGlobals.LangGroupAdditionalFiles == NULL)
{
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
}
ZeroMemory( FixedGlobals.LangGroupAdditionalFiles,
sizeof(NAMELIST) * iLangGroupCount );
for( i = 1; i <= iLangGroupCount; i++ )
{
lstrcpyn( szSectionName, _T("LG_INSTALL_"), AS(szSectionName) );
hrCat=StringCchCat( szSectionName, AS(szSectionName), _itot( i, szBuffer, 10 ) );
GetPrivateProfileString( szSectionName,
_T("CopyFiles"),
_T(""),
szIniBuffer,
StrBuffSize(szIniBuffer),
szIntlInf );
//
// Loop grabbing each of the sub-section names and inserting them into
// the namelist
//
pszIniBuffer = szIniBuffer;
while( GetCommaDelimitedEntry( szBuffer, &pszIniBuffer ) )
{
AddNameToNameListNoDuplicates( &SubSectionList,
szBuffer );
}
iSubSectionEntries = GetNameListSize( &SubSectionList );
for( j = 0; j < iSubSectionEntries; j++ )
{
pszSubSectionName = GetNameListName( &SubSectionList, j );
ReadAllFilesUnderSection( hInterntlInf,
pszSubSectionName,
&( FixedGlobals.LangGroupAdditionalFiles[i - 1] ) );
}
ResetNameList( &SubSectionList );
}
}
//----------------------------------------------------------------------------
//
// Function: BuildLanguageLists
//
// Purpose: Mallocs and fills in a LANGUAGEGROUP_LIST and a LANGUAGELOCALE_LIST
// which are lists that that maintain language settings read from intl.inf
//
// Adjusts the global variables FixedGlobals.LanguageGroupList and
// FixedGlobals.LanguageLocaleList to point to their respective lists
//
// Arguments: VOID
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID
BuildLanguageLists( VOID )
{
#define INTERNATIONAL_INF _T("intl.inf")
#define LANGUAGE_GROUP_NAME 1
#define LANGUAGE_GROUP_ID 3
#define LANGUAGE_LOCALE_NAME 1
#define LANGUAGE_LOCALE_ID 0
#define KEYBOARD_LAYOUT 5
HINF hInterntlInf = NULL;
INFCONTEXT LangInfContext = { 0 };
INFCONTEXT LocaleInfContext = { 0 };
TCHAR szBuffer[MAX_STRING_LEN] = _T("");
INT iLangGroupCount = 0;
LANGUAGEGROUP_LIST *LangNode = NULL;
LANGUAGEGROUP_LIST *CurrentLangNode = NULL;
LANGUAGELOCALE_LIST *LocaleNode = NULL;
LANGUAGELOCALE_LIST *CurrentLocaleNode = NULL;
//
// Read in from the file intl.inf and build the language list
//
hInterntlInf = SetupOpenInfFile( INTERNATIONAL_INF, NULL, INF_STYLE_WIN4, NULL );
if( hInterntlInf == INVALID_HANDLE_VALUE ) {
// ISSUE-2002/02/28-stelo - should allow browse for file here?
}
LangInfContext.Inf = hInterntlInf;
LangInfContext.CurrentInf = hInterntlInf;
LocaleInfContext.Inf = hInterntlInf;
LocaleInfContext.CurrentInf = hInterntlInf;
//
// For each Language Group, add its corresponding data to the language group list
//
SetupFindFirstLine( hInterntlInf, _T("LanguageGroups"), NULL, &LangInfContext );
do {
LangNode = malloc( sizeof( LANGUAGEGROUP_LIST ) );
if (LangNode == NULL)
{
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
}
else
{
LangNode->next = NULL;
SetupGetStringField( &LangInfContext,
0,
LangNode->szLanguageGroupId,
MAX_STRING_LEN,
NULL );
SetupGetStringField( &LangInfContext,
1,
LangNode->szLanguageGroupName,
MAX_STRING_LEN,
NULL );
SetupGetStringField( &LangInfContext,
2,
LangNode->szLangFilePath,
MAX_STRING_LEN,
NULL );
}
// See if the LanguageGroupList has been assigned yet. It will not be if
// it is NULL. If currentLangNode is NULL, then resetart LanguageGroupList
// at the new LangNode as well.
if( (FixedGlobals.LanguageGroupList == NULL) ||
(CurrentLangNode == NULL))
{
FixedGlobals.LanguageGroupList = LangNode;
CurrentLangNode = LangNode;
}
else
{
CurrentLangNode->next = LangNode;
CurrentLangNode = CurrentLangNode->next;
}
iLangGroupCount++;
} // move to the next line of the .inf file
while( SetupFindNextLine( &LangInfContext, &LangInfContext ) );
//
// For each locale, add its corresponding data to the language locale list
//
SetupFindFirstLine( hInterntlInf, _T("Locales"), NULL, &LocaleInfContext );
do
{
LocaleNode = malloc( sizeof( LANGUAGELOCALE_LIST ) );
if (LocaleNode == NULL)
{
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
}
else
{
LocaleNode->next = NULL;
//
// Get the Language Locale Name
//
SetupGetStringField( &LocaleInfContext,
LANGUAGE_LOCALE_NAME,
LocaleNode->szLanguageLocaleName,
MAX_STRING_LEN,
NULL );
//
// Get the Language Locale ID
//
SetupGetStringField( &LocaleInfContext,
LANGUAGE_LOCALE_ID,
LocaleNode->szLanguageLocaleId,
MAX_STRING_LEN,
NULL );
//
// Get the Keyboard Layout
//
SetupGetStringField( &LocaleInfContext,
KEYBOARD_LAYOUT,
LocaleNode->szKeyboardLayout,
MAX_STRING_LEN,
NULL );
//
// Get the Language Group ID
//
SetupGetStringField( &LocaleInfContext,
LANGUAGE_GROUP_ID,
szBuffer,
MAX_STRING_LEN,
NULL );
//
// Find the Language Group string that goes with the Language Group ID
//
for( CurrentLangNode = FixedGlobals.LanguageGroupList;
CurrentLangNode != NULL;
CurrentLangNode = CurrentLangNode->next ) {
if( lstrcmp( CurrentLangNode->szLanguageGroupId,
szBuffer ) == 0 ) {
LocaleNode->pLanguageGroup = CurrentLangNode;
break; // found what we were looking for so break
}
}
}
//
// Add the new node into the linked list
//
// See if the LanguageLocaleList has been assigned yet. It will not be if
// it is NULL. If currentLocaleNode is NULL, then resetart LanguageLocaleList
// at the new LocaleNode as well.
if( (FixedGlobals.LanguageLocaleList == NULL) ||
(CurrentLocaleNode == NULL))
{
FixedGlobals.LanguageLocaleList = LocaleNode;
CurrentLocaleNode = LocaleNode;
}
else
{
CurrentLocaleNode->next = LocaleNode;
CurrentLocaleNode = CurrentLocaleNode->next;
}
} // move to the next line of the .inf file
while( SetupFindNextLine( &LocaleInfContext, &LocaleInfContext ) );
//
// Set the default locale
//
SetupFindFirstLine( hInterntlInf,
_T("DefaultValues"),
NULL,
&LocaleInfContext );
SetupGetStringField( &LocaleInfContext,
1,
g_szDefaultLocale,
MAX_LANGUAGE_LEN,
NULL );
BuildAdditionalLanguageList( hInterntlInf, iLangGroupCount );
SetupCloseInfFile( hInterntlInf );
}
//----------------------------------------------------------------------------
//
// Function: LoadStringsAndDefaultsForNetworkComponents
//
// Purpose:
//
// Arguments: VOID
//
// Returns: VOID
//
//----------------------------------------------------------------------------
static VOID
LoadStringsAndDefaultsForNetworkComponents( VOID )
{
//
// Load strings from resources and setup initial values for global
// network components list
//
NETWORK_COMPONENT *pNetComponent;
pNetComponent = malloc( sizeof( NETWORK_COMPONENT ) );
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
NetSettings.NetComponentsList = pNetComponent;
pNetComponent->StrComponentName = MyLoadString( IDS_CLIENT_FOR_MS_NETWORKS );
pNetComponent->StrComponentDescription = MyLoadString( IDS_CLIENT_FOR_MS_NETWORKS_DESC );
pNetComponent->iPosition = MS_CLIENT_POSITION;
pNetComponent->ComponentType = CLIENT;
pNetComponent->bHasPropertiesTab = TRUE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = TRUE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_CLIENT_FOR_NETWARE );
pNetComponent->StrComponentDescription = MyLoadString( IDS_CLIENT_FOR_NETWARE_DESC );
pNetComponent->iPosition = NETWARE_CLIENT_POSITION;
pNetComponent->ComponentType = CLIENT;
pNetComponent->bHasPropertiesTab = TRUE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = TRUE;
pNetComponent->dwPlatforms = 0x0 | WORKSTATION_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_FILE_AND_PRINT_SHARING );
pNetComponent->StrComponentDescription = MyLoadString( IDS_FILE_AND_PRINT_SHARING_DESC );
pNetComponent->iPosition = FILE_AND_PRINT_SHARING_POSITION;
pNetComponent->ComponentType = SERVICE;
pNetComponent->bHasPropertiesTab = FALSE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_PACKET_SCHEDULING_DRIVER );
pNetComponent->StrComponentDescription = MyLoadString( IDS_PACKET_SCHEDULING_DRIVER_DESC );
pNetComponent->iPosition = PACKET_SCHEDULING_POSITION;
pNetComponent->ComponentType = SERVICE;
pNetComponent->bHasPropertiesTab = FALSE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_APPLETALK_PROTOCOL );
pNetComponent->StrComponentDescription = MyLoadString( IDS_APPLETALK_PROTOCOL_DESC );
pNetComponent->iPosition = APPLETALK_POSITION;
pNetComponent->ComponentType = PROTOCOL;
pNetComponent->bHasPropertiesTab = FALSE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_TCPIP );
pNetComponent->StrComponentDescription = MyLoadString( IDS_TCPIP_DESC );
pNetComponent->iPosition = TCPIP_POSITION;
pNetComponent->ComponentType = PROTOCOL;
pNetComponent->bHasPropertiesTab = TRUE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_NETWORK_MONITOR_AGENT );
pNetComponent->StrComponentDescription = MyLoadString( IDS_NETWORK_MONITOR_AGENT_DESC );
pNetComponent->iPosition = NETWORK_MONITOR_AGENT_POSITION;
pNetComponent->ComponentType = PROTOCOL;
pNetComponent->bHasPropertiesTab = FALSE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_IPX_PROTOCOL );
pNetComponent->StrComponentDescription = MyLoadString( IDS_IPX_PROTOCOL_DESC );
pNetComponent->iPosition = IPX_POSITION;
pNetComponent->ComponentType = PROTOCOL;
pNetComponent->bHasPropertiesTab = TRUE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_DLC_PROTOCOL );
pNetComponent->StrComponentDescription = MyLoadString( IDS_DLC_PROTOCOL_DESC );
pNetComponent->iPosition = DLC_POSITION;
pNetComponent->ComponentType = PROTOCOL;
pNetComponent->bHasPropertiesTab = FALSE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_NETBEUI_PROTOCOL );
pNetComponent->StrComponentDescription = MyLoadString( IDS_NETBEUI_PROTOCOL_DESC );
pNetComponent->iPosition = NETBEUI_POSITION;
pNetComponent->ComponentType = PROTOCOL;
pNetComponent->bHasPropertiesTab = FALSE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_SAP_AGENT );
pNetComponent->StrComponentDescription = MyLoadString( IDS_SAP_AGENT_DESC );
pNetComponent->iPosition = SAP_AGENT_POSITION;
pNetComponent->ComponentType = SERVICE;
pNetComponent->bHasPropertiesTab = FALSE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = FALSE;
pNetComponent->dwPlatforms = 0x0 | PERSONAL_INSTALL | WORKSTATION_INSTALL | SERVER_INSTALL;
pNetComponent->next = malloc( sizeof( NETWORK_COMPONENT ) );
pNetComponent = pNetComponent->next;
if (pNetComponent == NULL)
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
pNetComponent->StrComponentName = MyLoadString( IDS_GATEWAY_FOR_NETWARE );
pNetComponent->StrComponentDescription = MyLoadString( IDS_GATEWAY_FOR_NETWARE_DESC );
pNetComponent->iPosition = GATEWAY_FOR_NETWARE_POSITION;
pNetComponent->ComponentType = CLIENT;
pNetComponent->bHasPropertiesTab = TRUE;
pNetComponent->bInstalled = FALSE;
pNetComponent->bSysprepSupport = TRUE;
pNetComponent->dwPlatforms = 0x0 | SERVER_INSTALL;
pNetComponent->next = NULL; // terminate the list
NetSettings.NumberOfNetComponents = 11;
}