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.
 
 
 
 
 
 

498 lines
12 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1995 **/
/**********************************************************************/
/*
dhcpopt.cpp
Defines the class behaviors for the application.
FILE HISTORY:
This program reads a CSV-formatted Excel spreadsheet containing the standard
(globally defined) DHCP option information. This data is parsed into
a CObListParamTypes, each element of which contains a default value.
Here are a couple of example lines:
255,End,Generated,-,y,y,1,Indicates end of options in DHCP packet,
21,Max DG reassembly size,Short,-,n,n,2,Maximum size datagram for reass. by client; max 576,
22,Default time-to-live,Octet,-,?,y,1,default TTL for client's use on outgoing DGs,
The fields, in order, are:
Option number, numeric. if this is empty or non-numeric, the line is skipped.
Option name, string.
Option type, string. one of "generated", "IP addr", "string", etc.
Array flag, character: 'Y' if it's an array.
Length, numeric: length of each element.
Description, string: comment info
Remark, string: ignored
*/
#include "stdafx.h"
#include "options.h"
#include "dhcpopt.h" // From the MC File.
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
const char * pszResourceName = "DHCPOPT" ;
const char * pszResourceType = "TEXT" ;
const int cchFieldMax = 500 ;
enum OPT_FIELD
{
OPTF_OPTION,
OPTF_NAME,
OPTF_TYPE,
OPTF_ARRAY_FLAG,
OPTF_LENGTH,
OPTF_DESCRIPTION,
OPTF_REMARK,
OPTF_MAX
};
typedef struct
{
int eOptType ;
const char * pszOptTypeName ;
} OPT_TOKEN ;
OPT_TOKEN aOptToken [] =
{
{ DhcpIpAddressOption, "IP Addr" },
{ DhcpIpAddressOption, "IPAddr" },
{ DhcpIpAddressOption, "IP Address" },
{ DhcpIpAddressOption, "IP Pairs" },
{ DhcpByteOption, "byte" },
{ DhcpByteOption, "boolean" },
{ DhcpByteOption, "octet" },
{ DhcpWordOption, "short" },
{ DhcpDWordOption, "long" },
{ DhcpDWordDWordOption, "double" },
{ DhcpStringDataOption, "string" },
{ DhcpBinaryDataOption, "binary" },
{ -1, "generated" },
{ -1, NULL }
};
int
recognizeToken (
OPT_TOKEN * apToken,
const char * pszToken
)
{
int i ;
for ( i = 0 ;
apToken[i].pszOptTypeName && ::lstrcmpi( apToken[i].pszOptTypeName, pszToken ) != 0 ;
i++ ) ;
return apToken[i].eOptType ;
}
const char *
skipToNextLine (
const char * pszLine
)
{
for ( ; *pszLine && *pszLine != '\n' ; pszLine++ ) ;
if ( *pszLine )
{
pszLine++ ; // Don't overscan buffer delimiter.
}
return pszLine ;
}
BOOL
skipWs (
const char * * ppszLine
)
{
const char * pszLine ;
BOOL bResult = FALSE ;
for ( pszLine = *ppszLine ; *pszLine ; pszLine++ )
{
switch ( *pszLine )
{
case ' ':
case '\r':
case '\t':
break ;
default:
bResult = TRUE ;
break ;
}
if ( bResult )
{
break ;
}
}
*ppszLine = pszLine ;
return *pszLine != 0 ;
}
const char *
scanNextField (
const char * pszLine,
char * pszOut,
int cFieldSize
)
{
//
// Skip junk; return NULL if end-of-buffer.
//
if ( ! skipWs( & pszLine ) )
{
return NULL ;
}
int cch = 0 ;
BOOL bDone = FALSE ;
char * pszField = pszOut ;
char ch ;
if ( *pszLine == '\"' )
{
//
// Quoted string.
//
while ( ch = *++pszLine )
{
if ( ch == '\r' )
{
continue ;
}
if ( ch == '\n' || ch == '\"' || cch == cFieldSize )
{
break ;
}
*pszField++ = ch ;
cch++ ;
}
if ( ch == '\"' )
{
pszLine++ ;
}
}
else
while ( ! bDone )
{
ch = *pszLine++ ;
ASSERT( ch != 0 ) ;
switch ( ch )
{
case '\n':
pszLine-- ; // Don't scan past the NL
case ',':
case '\r':
bDone = TRUE ;
break ;
default:
if ( cch < cFieldSize )
{
*pszField++ = ch ;
cch++ ;
}
break ;
}
}
//
// Trim spaces off the end of the field.
//
while ( pszField > pszOut && *(pszField-1) == ' ' )
{
pszField-- ;
}
*pszField = 0 ;
return pszLine ;
}
BOOL
allDigits (
const char * psz
)
{
for ( ; *psz ; psz++ )
{
if ( ! isdigit( *psz ) )
{
return FALSE ;
}
}
return TRUE ;
}
BOOL
scanNextParamType (
const char * * ppszText,
CDhcpParamType * * ppParamType
)
{
char szField [ cchFieldMax ] ;
char szName [ cchFieldMax ] ;
char szComment [ cchFieldMax ] ;
BOOL bResult = TRUE ;
BOOL bArray = FALSE ;
int eofld, cch, itype, cbLgt ;
const char * pszText = *ppszText ;
CDhcpParamType * pParamType = NULL ;
DHCP_OPTION_ID did ;
DHCP_OPTION_DATA_TYPE dtype ;
for ( eofld = OPTF_OPTION ;
pszText = scanNextField( pszText, szField, sizeof szField ) ;
eofld++ )
{
cch = ::strlen( szField ) ;
switch ( eofld )
{
case OPTF_OPTION:
if ( cch > 0 && allDigits( szField ) )
{
did = (DHCP_OPTION_ID) ::atoi( szField ) ;
}
else
{
bResult = FALSE ;
}
break ;
case OPTF_NAME:
if ( ::strlen( szField ) == 0 )
{
bResult = FALSE ;
break ;
}
::strcpy( szName, szField ) ;
break ;
case OPTF_TYPE:
if ( (itype = recognizeToken( aOptToken, szField )) < 0 )
{
TRACEEOLID( "options CSV ID " << did
<< ", cannot recognize type " << szField ) ;
bResult = FALSE ;
break ;
}
dtype = (DHCP_OPTION_DATA_TYPE) itype ;
break ;
case OPTF_ARRAY_FLAG:
bArray = szField[0] == 'y' || szField[0] == 'Y' ;
break ;
case OPTF_LENGTH:
cbLgt = ::atoi( szField ) ;
break ;
case OPTF_DESCRIPTION:
::strcpy( szComment, szField ) ;
break ;
case OPTF_REMARK:
case OPTF_MAX:
break ;
}
if ( eofld == OPTF_REMARK || ! bResult )
{
pszText = skipToNextLine( pszText ) ;
if ( *pszText == 0 )
{
pszText = NULL ;
}
break;
}
}
if ( bResult )
{
pParamType = new CDhcpParamType( did, dtype, szName, szComment,
bArray ? DhcpArrayTypeOption
: DhcpUnaryElementTypeOption ) ;
bResult = pParamType->QueryError() == 0 ;
}
if ( bResult )
{
*ppParamType = pParamType ;
}
else
{
delete pParamType ;
*ppParamType = NULL ;
}
*ppszText = pszText ;
return pszText != NULL ;
}
//
// Build the master list of default (global) parameter types and default values.
//
CObListParamTypes *
CDhcpApp :: QueryMasterOptionList ()
{
APIERR err = 0 ;
CObListParamTypes * poblTypes = NULL ;
CDhcpParamType * pParamType ;
HRSRC hRes = NULL ;
HGLOBAL hText = NULL ;
char * pszText = NULL ;
const char * pcszText ;
size_t cchText;
LPTSTR * szParms;
char szUnknown[] = "(Unknown)"; // This is just to prevent a GP fault (should not be in resource)
CATCH_MEM_EXCEPTION
{
do
{
/*
hRes = ::FindResource( m_hInstance,
pszResourceName,
pszResourceType ) ;
if ( hRes == NULL )
{
TRACEEOLID( "Unable to find options CSV file resource " << pszResourceName ) ;
break ;
}
cchText = ::SizeofResource( m_hInstance, hRes ) ;
if ( (hText = ::LoadResource( m_hInstance, hRes )) == NULL )
{
TRACEEOLID( "Unable to load options CSV file resource " << pszResourceName ) ;
break ;
}
pszText = new char[ cchText + 2 ] ;
::memcpy( (void *) pszText, ::LockResource( hText ), cchText ) ;
for ( cch = 0 ; cch < cchText ; cch++ )
{
if ( pszText[cch] == 0 || pszText[cch] == 0x1a )
{
break ;
}
}
pszText[cch] = 0 ;
*/
//
// IMPORTANT!!! There is no way to determine from the .mc file how many
// options are defined. This number is therefore hard-coded
// here, and should reflect the highest parameter number in
// the .mc file.
//
// BUGBUG (t-danmo): The extra 16 entries are for safety
// when calling FormatMessage().
szParms = new LPTSTR[IDS_OPTION_MAX+16];
TRACEEOLID("Now building list of option parameters");
CString strOptionText;
// Initialize the extra entries to something that will not GP fault.
for (int i = 0; i < 16; i++)
{
szParms[IDS_OPTION_MAX+i] = szUnknown;
}
//
// Don't mess with the order of the ID definitions!!!
//
for (i = 0; i < IDS_OPTION_MAX; ++i)
{
if (strOptionText.LoadString(IDS_OPTION1 + i))
{
ASSERT(strOptionText.GetLength() > 0);
szParms[i] = new TCHAR[strOptionText.GetLength()+1];
::strcpy(szParms[i], (LPCSTR)strOptionText);
}
else
{
//
// Failed to load the string from the resource
// for some reason.
//
TRACEEOLID("WARNING: Failed to load option text " << IDS_OPTION1 + i);
err = ::GetLastError();
szParms[i] = szUnknown; // Prevent from GP faulting
break;
}
}
if (err != ERROR_SUCCESS)
{
break;
}
cchText = ::FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_HMODULE
| FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL, // hModule
DHCP_OPTIONS, // dwMessageId loaded from a system dll
0L, // dwLanguageId
OUT (LPTSTR)&pszText,
0,
(va_list *)szParms
);
if (cchText == 0)
{
err = ::GetLastError();
break;
}
//
// Walk the resource, parsing each line. If the line converts
// to a tangible type, add it to the list.
//
poblTypes = new CObListParamTypes ;
for ( pcszText = pszText ; scanNextParamType( & pcszText, & pParamType ) ; )
{
if ( pParamType )
{
poblTypes->AddTail( pParamType ) ;
}
}
} while ( FALSE ) ;
}
END_MEM_EXCEPTION( err )
//delete pszText ;
//if ( hText )
//{
//UnlockResource( hText ) ;
//::FreeResource( hText ) ;
//}
for (int i = 0; i < IDS_OPTION_MAX; ++i)
{
if (szParms[i] != szUnknown)
delete[] szParms[i];
}
delete[] szParms;
::LocalFree(pszText);
return poblTypes ;
}
// End of DHCPMOPT.CPP