Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1024 lines
24 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
dhcpcli.c
Abstract:
This is the API tester for the DHCP client.
To build, 'nmake UMTEST=dhcpcli'
Author:
Manny Weiser (mannyw) 1-Dec-1992
Environment:
User Mode - Win32
Revision History:
Madan Appiah (madana) 21-Oct-1993
--*/
#include "precomp.h"
#include "dhcploc.h"
#include "dhcppro.h"
#include "dhcpcapi.h"
#include "lmcons.h"
#include "conio.h"
DWORD // win32 status
DhcpAcquireParametersByBroadcast( // acquire/renew a lease
IN LPWSTR AdapterName // adapter to acquire lease on
);
extern DWORD DhcpStaticRefreshParams(IN LPWSTR Adapter);
#define IP_ADDRESS_STRING L"IPAddress"
#define IP_ADDRESS_STRING_TYPE REG_MULTI_SZ
#define SUBNET_MASK_STRING L"SubnetMask"
#define SUBNET_MASK_STRING_TYPE REG_MULTI_SZ
#define USAGE_MESSAGE0 \
"Usage: dhcpcli { " \
"renew,release,set,enabledhcp,disabledhcp,timestamp," \
"leasetest,fbrefresh, reinit, staticrefresh } parameters\n"
#define USAGE_MESSAGE1 "Usage: dhcpcli renew adapter\n"
#define USAGE_MESSAGE2 "Usage: dhcpcli release adapter\n"
#define USAGE_MESSAGE3 "Usage: dhcpcli set ip-address subnet-mask adapter index \n"
#define USAGE_MESSAGE4 "Usage: dhcpcli enabledhcp adapter\n"
#define USAGE_MESSAGE5 "Usage: dhcpcli disabledhcp adapter ip-address subnet-mask \n"
#define USAGE_MESSAGE6 "Usage: dhcpcli timestamp Value\n"
#define USAGE_MESSAGE7 "Usage: dhcpcli leasetest adapter-ip-addres hardware-address\n"
#define USAGE_MESSAGE8 "Usage: dhcpcli fbrefresh adapter\n"
#define USAGE_MESSAGE9 "Usage: dhcpcli reinit adapter\n"
#define USAGE_MESSAGE10 "Usage: dhcpcli staticrefresh adapter\n"
DWORD
GetRegistryString(
HKEY Key,
LPWSTR ValueStringName,
LPWSTR *String,
LPDWORD StringSize
)
/*++
Routine Description:
This function retrieves the specified string value from the
registry. It allocates local memory for the returned string.
Arguments:
Key : registry handle to the key where the value is.
ValueStringName : name of the value string.
String : pointer to a location where the string pointer is returned.
StringSize : size of the string data returned. Optional
Return Value:
The status of the operation.
--*/
{
DWORD Error;
DWORD LocalValueType;
DWORD ValueSize;
LPWSTR LocalString;
DhcpAssert( *String == NULL );
//
// Query DataType and BufferSize.
//
Error = RegQueryValueEx(
Key,
ValueStringName,
0,
&LocalValueType,
NULL,
&ValueSize );
if( Error != ERROR_SUCCESS ) {
return(Error);
}
DhcpAssert( (LocalValueType == REG_SZ) ||
(LocalValueType == REG_MULTI_SZ) );
if( ValueSize == 0 ) {
*String = NULL;
*StringSize = 0;
return( ERROR_SUCCESS );
}
//
// now allocate memory for string data.
//
LocalString = DhcpAllocateMemory( ValueSize );
if(LocalString == NULL) {
return( ERROR_NOT_ENOUGH_MEMORY );
}
//
// Now query the string data.
//
Error = RegQueryValueEx(
Key,
ValueStringName,
0,
&LocalValueType,
(LPBYTE)(LocalString),
&ValueSize );
if( Error != ERROR_SUCCESS ) {
DhcpFreeMemory(LocalString);
return(Error);
}
*String = LocalString;
if( StringSize != NULL ) {
*StringSize = ValueSize;
}
return( ERROR_SUCCESS );
}
DWORD
RegSetIpAddress(
HKEY KeyHandle,
LPWSTR ValueName,
DWORD ValueType,
DHCP_IP_ADDRESS IpAddress
)
/*++
Routine Description:
This function sets IpAddress Value in the registry.
Arguments:
KeyHandle - handle to the key.
ValueName - name of the value field.
ValueType - Type of the value field.
IpAddress - Ipaddress to be set.
Return Value:
Registry Error.
--*/
{
DWORD Error;
LPSTR AnsiAddressString;
WCHAR UnicodeAddressBuf[DOT_IP_ADDR_SIZE];
LPWSTR UnicodeAddressString;
LPWSTR MultiIpAddressString = NULL;
LPWSTR NewMultiIpAddressString = NULL;
DWORD MultiIpAddressStringSize;
DWORD NewMultiIpAddressStringSize;
DWORD FirstOldIpAddressSize;
AnsiAddressString = inet_ntoa( *(struct in_addr *)&IpAddress );
UnicodeAddressString = DhcpOemToUnicode(
AnsiAddressString,
UnicodeAddressBuf );
DhcpAssert( UnicodeAddressString != NULL );
if( ValueType == REG_SZ ) {
Error = RegSetValueEx(
KeyHandle,
ValueName,
0,
ValueType,
(LPBYTE)UnicodeAddressString,
(wcslen(UnicodeAddressString) + 1) * sizeof(WCHAR) );
goto Cleanup;
}
DhcpAssert( ValueType == REG_MULTI_SZ );
//
// replace the first IpAddress.
//
//
// query current multi-IpAddress string.
//
Error = GetRegistryString(
KeyHandle,
ValueName,
&MultiIpAddressString,
&MultiIpAddressStringSize );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// allocate new address string.
//
DhcpAssert(MultiIpAddressString != NULL);
FirstOldIpAddressSize =
(wcslen(MultiIpAddressString) + 1) * sizeof(WCHAR);
NewMultiIpAddressStringSize =
MultiIpAddressStringSize - FirstOldIpAddressSize +
(wcslen(UnicodeAddressString) + 1) * sizeof(WCHAR);
NewMultiIpAddressString = DhcpAllocateMemory( NewMultiIpAddressStringSize );
if( NewMultiIpAddressString == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// make new address string first.
//
wcscpy( NewMultiIpAddressString, UnicodeAddressString );
//
// copy rest of the old addresses
//
RtlCopyMemory(
(LPBYTE)NewMultiIpAddressString +
(wcslen(UnicodeAddressString) + 1) * sizeof(WCHAR),
(LPBYTE)MultiIpAddressString + FirstOldIpAddressSize,
MultiIpAddressStringSize - FirstOldIpAddressSize );
Error = RegSetValueEx(
KeyHandle,
ValueName,
0,
ValueType,
(LPBYTE)NewMultiIpAddressString,
NewMultiIpAddressStringSize );
Cleanup:
if( MultiIpAddressString != NULL) {
DhcpFreeMemory( MultiIpAddressString );
}
if( NewMultiIpAddressString != NULL) {
DhcpFreeMemory( NewMultiIpAddressString );
}
return( Error );
}
EnableDhcp(
char **argv
)
{
DWORD Error;
LPWSTR RegKey = NULL;
HKEY KeyHandle = NULL;
WCHAR AdapterNameBuffer[PATHLEN];
LPWSTR AdapterName;
DWORD EnableDhcp;
AdapterName = DhcpOemToUnicode( argv[0], AdapterNameBuffer );
if( AdapterName == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// make NIC IP parameter key.
//
RegKey = DhcpAllocateMemory(
(wcslen(DHCP_SERVICES_KEY) +
wcslen(REGISTRY_CONNECT_STRING) +
wcslen(AdapterName) +
wcslen(DHCP_ADAPTER_PARAMETERS_KEY) + 1) *
sizeof(WCHAR) ); // termination char.
if( RegKey == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
#if defined(_PNP_POWER_)
wcscpy( RegKey, DHCP_SERVICES_KEY );
wcscat( RegKey, DHCP_ADAPTER_PARAMETERS_KEY );
wcscat( RegKey, REGISTRY_CONNECT_STRING );
wcscat( RegKey, AdapterName );
#else
wcscpy( RegKey, DHCP_SERVICES_KEY );
wcscat( RegKey, REGISTRY_CONNECT_STRING );
wcscat( RegKey, AdapterName );
wcscat( RegKey, DHCP_ADAPTER_PARAMETERS_KEY );
#endif _PNP_POWER_
//
// open this key.
//
Error = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
RegKey,
0, // Reserved field
DHCP_CLIENT_KEY_ACCESS,
&KeyHandle
);
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// Set DHCP switch.
//
EnableDhcp = TRUE;
Error = RegSetValueEx(
KeyHandle,
DHCP_ENABLE_STRING,
0,
DHCP_ENABLE_STRING_TYPE,
(LPBYTE)&EnableDhcp,
sizeof(EnableDhcp) );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// set Ipaddress and SubnetMask to zero.
//
Error = RegSetIpAddress(
KeyHandle,
IP_ADDRESS_STRING,
IP_ADDRESS_STRING_TYPE,
0 );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Error = RegSetIpAddress(
KeyHandle,
DHCP_IP_ADDRESS_STRING,
DHCP_IP_ADDRESS_STRING_TYPE,
0 );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Error = RegSetIpAddress(
KeyHandle,
SUBNET_MASK_STRING,
SUBNET_MASK_STRING_TYPE,
0xff );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Error = RegSetIpAddress(
KeyHandle,
DHCP_SUBNET_MASK_STRING,
DHCP_SUBNET_MASK_STRING_TYPE,
0xff );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// Call config API to indicate to DHCP service.
//
Error = DhcpNotifyConfigChange(
L"",
AdapterName,
TRUE,
0, // AdapterIndex
0, // IpAddress
0, // SubnetMask
DhcpEnable );
Cleanup:
if( RegKey != NULL ) {
DhcpFreeMemory( RegKey );
}
if( KeyHandle != NULL ) {
RegCloseKey( KeyHandle );
}
return(Error);
}
DisableDhcp(
char **argv
)
{
DWORD Error;
LPWSTR RegKey = NULL;
HKEY KeyHandle = NULL;
DWORD IpAddress;
DWORD SubnetMask;
WCHAR AdapterNameBuffer[PATHLEN];
LPWSTR AdapterName;
DWORD EnableDhcp;
AdapterName = DhcpOemToUnicode( argv[0], AdapterNameBuffer );
if( AdapterName == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
IpAddress = inet_addr( argv[1] );
SubnetMask = inet_addr( argv[2] );
//
// make NIC IP parameter key.
//
RegKey = DhcpAllocateMemory(
(wcslen(DHCP_SERVICES_KEY) +
wcslen(REGISTRY_CONNECT_STRING) +
wcslen(AdapterName) +
wcslen(DHCP_ADAPTER_PARAMETERS_KEY) + 1) *
sizeof(WCHAR) ); // termination char.
if( RegKey == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
#if defined(_PNP_POWER_)
wcscpy( RegKey, DHCP_SERVICES_KEY );
wcscat( RegKey, DHCP_ADAPTER_PARAMETERS_KEY );
wcscat( RegKey, REGISTRY_CONNECT_STRING );
wcscat( RegKey, AdapterName );
#else
wcscpy( RegKey, DHCP_SERVICES_KEY );
wcscat( RegKey, REGISTRY_CONNECT_STRING );
wcscat( RegKey, AdapterName );
wcscat( RegKey, DHCP_ADAPTER_PARAMETERS_KEY );
#endif _PNP_POWER_
//
// open this key.
//
Error = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
RegKey,
0, // Reserved field
DHCP_CLIENT_KEY_ACCESS,
&KeyHandle
);
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// Set DHCP switch.
//
EnableDhcp = FALSE;
Error = RegSetValueEx(
KeyHandle,
DHCP_ENABLE_STRING,
0,
DHCP_ENABLE_STRING_TYPE,
(LPBYTE)&EnableDhcp,
sizeof(EnableDhcp) );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// set Ipaddress and SubnetMask to zero.
//
Error = RegSetIpAddress(
KeyHandle,
IP_ADDRESS_STRING,
IP_ADDRESS_STRING_TYPE,
IpAddress );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Error = RegSetIpAddress(
KeyHandle,
DHCP_IP_ADDRESS_STRING,
DHCP_IP_ADDRESS_STRING_TYPE,
0 );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Error = RegSetIpAddress(
KeyHandle,
SUBNET_MASK_STRING,
SUBNET_MASK_STRING_TYPE,
SubnetMask );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
Error = RegSetIpAddress(
KeyHandle,
DHCP_SUBNET_MASK_STRING,
DHCP_SUBNET_MASK_STRING_TYPE,
0xff );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// Call config API to indicate to DHCP service.
//
Error = DhcpNotifyConfigChange(
L"",
AdapterName,
TRUE,
0, // AdapterIndex
IpAddress,
SubnetMask,
DhcpDisable );
Cleanup:
if( RegKey != NULL ) {
DhcpFreeMemory( RegKey );
}
if( KeyHandle != NULL ) {
RegCloseKey( KeyHandle );
}
return(Error);
}
SetIpAddress(
char **argv
)
{
DWORD Error;
DWORD IpAddress;
DWORD SubnetMask;
WCHAR AdapterNameBuffer[PATHLEN];
LPWSTR AdapterName;
DWORD AdapterIndex;
IpAddress = inet_addr( argv[0] );
SubnetMask = inet_addr( argv[1] );
AdapterName = DhcpOemToUnicode( argv[2], AdapterNameBuffer );
if( AdapterName == NULL ) {
return( ERROR_NOT_ENOUGH_MEMORY );
}
AdapterIndex = atoi( argv[3] );
Error = DhcpNotifyConfigChange(
L"",
AdapterName,
TRUE,
AdapterIndex,
IpAddress,
SubnetMask,
IgnoreFlag );
return( Error );
}
VOID
PrintClientLeaseInfo(
LPDHCP_LEASE_INFO LeaseInfo
)
{
DWORD i;
DWORD DataLength;
LPBYTE Data;
if( LeaseInfo == NULL ) {
printf( "LeaseInfo is NULL .\n" );
return;
}
printf("ClientInfo :\n");
printf("\tClient Hardware Address = ");
DataLength = LeaseInfo->ClientUID.ClientUIDLength;
Data = LeaseInfo->ClientUID.ClientUID;
for( i = 0; i < DataLength; i++ ) {
printf("%.2lx", (DWORD)Data[i]);
}
printf( "\n" );
printf("\tIP Address = %s.\n",
DhcpIpAddressToDottedString(LeaseInfo->IpAddress));
printf("\tSubnetMask = %s.\n",
DhcpIpAddressToDottedString(LeaseInfo->SubnetMask));
printf("\tDhcpServerAddress = %s.\n",
DhcpIpAddressToDottedString(LeaseInfo->DhcpServerAddress));
printf("\tLease = %ld secs.\n", LeaseInfo->Lease );
printf("\tLease Obtained at %s", ctime(&LeaseInfo->LeaseObtained) );
printf("\tT1 time is %s", ctime(&LeaseInfo->T1Time) );
printf("\tT2 time is %s", ctime(&LeaseInfo->T2Time) );
printf("\tLease Expires at %s", ctime(&LeaseInfo->LeaseExpires) );
return;
}
DWORD
DhcpTestLease(
LPSTR AdapterIpAddressString,
LPSTR HardwareAddressString
)
{
#define MAX_ADDRESS_LENGTH 64 // 64 bytes
DWORD Error;
DWORD AdapterIpAddress;
DHCP_CLIENT_UID ClientUID;
BYTE Address[MAX_ADDRESS_LENGTH];
DWORD i;
LPDHCP_LEASE_INFO LeaseInfo = NULL;
LPDHCP_OPTION_INFO OptionInfo;
DHCP_OPTION_LIST OptionList;
CHAR ch;
AdapterIpAddress = ntohl( inet_addr( AdapterIpAddressString ) );
ClientUID.ClientUIDLength = strlen(HardwareAddressString);
if( ClientUID.ClientUIDLength % 2 != 0 ) {
//
// address must be even length.
//
printf("DhcpTestLease: Hardware address must be even length.\n");
return( ERROR_INVALID_PARAMETER );
}
ClientUID.ClientUIDLength /= 2;
if( ClientUID.ClientUIDLength > MAX_ADDRESS_LENGTH ) {
printf("DhcpTestLease: hardware address is too long.\n");
return( ERROR_INVALID_PARAMETER );
}
i = DhcpStringToHwAddress( (LPSTR)Address, HardwareAddressString );
DhcpAssert( i == ClientUID.ClientUIDLength );
ClientUID.ClientUID = Address;
OptionList.NumOptions = 0;
OptionList.OptionIDArray = NULL;
Error = DhcpLeaseIpAddress(
AdapterIpAddress, // any subnet.
&ClientUID,
0, // desired address.
&OptionList, // option list - not supported
&LeaseInfo, // lease info returned.
&OptionInfo); // option data returned.
if( Error != ERROR_SUCCESS ) {
printf("DhcpLeaseIpAddress failed, %ld.\n", Error);
goto Cleanup;
}
PrintClientLeaseInfo( LeaseInfo );
printf("Renew the lease ? (Y/N) ");
do {
ch = (CHAR)getchar();
} while ( (ch != 'Y') && (ch != 'y') && (ch != 'N') && (ch != 'n') );
printf("%c\n", ch);
if( (ch == 'N') || (ch == 'n') ) {
printf( "NOTE: YOU HAVE CONSUMED AN IP ADDRESS FROM "
"THE DHCP SERVER. \n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
Error = DhcpRenewIpAddressLease(
AdapterIpAddress,
LeaseInfo,
&OptionList, // option list - not supported
&OptionInfo); // option data returned.
if( Error != ERROR_SUCCESS ) {
printf("DhcpRenewIpAddressLease failed, %ld.\n", Error);
goto Cleanup;
}
PrintClientLeaseInfo( LeaseInfo );
printf("Release the lease ? (Y/N) ");
do {
ch = (CHAR)getchar();
} while ( (ch != 'Y') && (ch != 'y') && (ch != 'N') && (ch != 'n') );
printf("%c\n", ch);
if( (ch == 'N') || (ch == 'n') ) {
printf( "NOTE: YOU HAVE CONSUMED AN IP ADDRESS FROM "
"THE DHCP SERVER. \n");
Error = ERROR_SUCCESS;
goto Cleanup;
}
Error = DhcpReleaseIpAddressLease(
AdapterIpAddress,
LeaseInfo );
if( Error != ERROR_SUCCESS ) {
printf("DhcpReleaseIpAddressLease failed, %ld.\n", Error);
goto Cleanup;
}
Error = ERROR_SUCCESS;
Cleanup:
if( LeaseInfo != NULL ) {
DhcpFreeMemory( LeaseInfo );
}
return( Error );
}
DWORD __cdecl
main(
int argc,
char **argv
)
{
DWORD error;
WCHAR AdapterNameBuffer[PATHLEN];
LPWSTR AdapterName;
//
// seed random generator.
//
srand( GetCurrentTime() );
if ( argc < 2) {
printf( USAGE_MESSAGE0 );
return( 1 );
}
if ( _stricmp( argv[1], "renew" ) == 0 ) {
if ( argc < 3) {
printf( USAGE_MESSAGE1 );
return( 1 );
}
AdapterName = DhcpOemToUnicode( argv[2], AdapterNameBuffer );
if( AdapterName == NULL ) {
error = ERROR_NOT_ENOUGH_MEMORY;
}
else {
error = DhcpAcquireParameters( AdapterName );
}
} else if ( _stricmp( argv[1], "fbrefresh" ) == 0 ) {
if ( argc < 3) {
printf( USAGE_MESSAGE8 );
return( 1 );
}
AdapterName = DhcpOemToUnicode( argv[2], AdapterNameBuffer );
if( AdapterName == NULL ) {
error = ERROR_NOT_ENOUGH_MEMORY;
}
else {
error = DhcpFallbackRefreshParams( AdapterName );
}
} else if ( _stricmp( argv[1], "release" ) == 0 ) {
if ( argc < 3) {
printf( USAGE_MESSAGE2 );
return( 1 );
}
AdapterName = DhcpOemToUnicode( argv[2], AdapterNameBuffer );
if( AdapterName == NULL ) {
error = ERROR_NOT_ENOUGH_MEMORY;
}
else {
error = DhcpReleaseParameters( AdapterName );
}
} else if ( _stricmp( argv[1], "set" ) == 0 ) {
if ( argc < 6) {
printf( USAGE_MESSAGE3 );
return( 1 );
}
error = SetIpAddress( &argv[2] );
} else if ( _stricmp( argv[1], "enabledhcp" ) == 0 ) {
if ( argc < 3) {
printf( USAGE_MESSAGE4 );
return( 1 );
}
error = EnableDhcp( &argv[2] );
} else if ( _stricmp( argv[1], "disabledhcp" ) == 0 ) {
if ( argc < 5) {
printf( USAGE_MESSAGE5 );
return( 1 );
}
error = DisableDhcp( &argv[2] );
} else if ( _stricmp( argv[1], "timestamp" ) == 0 ) {
time_t Time;
char *endptr;
if ( argc < 3) {
printf( USAGE_MESSAGE6 );
return( 1 );
}
Time = strtol( argv[2], &endptr, 0 );
if( (endptr != NULL) && (*endptr != '\0') ) {
printf( "Invalid Input, %s\n", endptr );
return( 1 );
}
printf("TimeStamp = %s\n", ctime(&Time) );
error = ERROR_SUCCESS;
} else if ( _stricmp( argv[1], "leasetest" ) == 0 ) {
if ( argc < 3) {
printf( USAGE_MESSAGE7 );
return( 1 );
}
error = DhcpTestLease( argv[2], argv[3] );
} else if ( _stricmp( argv[1], "reinit" ) == 0 ) {
if ( argc < 3) {
printf( USAGE_MESSAGE9 );
return( 1 );
}
AdapterName = DhcpOemToUnicode( argv[2], AdapterNameBuffer );
if( AdapterName == NULL ) {
error = ERROR_NOT_ENOUGH_MEMORY;
}
else {
error = DhcpAcquireParametersByBroadcast( AdapterName );
}
} else if ( _stricmp( argv[1], "staticrefresh" ) == 0 ) {
if ( argc < 3) {
AdapterName = NULL;
} else {
AdapterName = DhcpOemToUnicode( argv[2], AdapterNameBuffer );
if( AdapterName == NULL ) {
error = ERROR_NOT_ENOUGH_MEMORY;
goto error;
}
}
error = DhcpStaticRefreshParams( AdapterName );
} else {
printf("Unknown function %s\n", argv[1] );
error = ERROR_INVALID_FUNCTION;
}
error:
if( error != ERROR_SUCCESS ) {
printf("Result = %d\n", error );
}
else {
printf("Command completed successfully.\n");
}
return(0);
}
#if DBG
VOID
DhcpPrintRoutine(
IN DWORD DebugFlag,
IN LPSTR Format,
...
)
{
#define MAX_PRINTF_LEN 1024 // Arbitrary.
va_list arglist;
char OutputBuffer[MAX_PRINTF_LEN];
ULONG length = 0;
//
// Put a the information requested by the caller onto the line
//
va_start(arglist, Format);
length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
va_end(arglist);
DhcpAssert(length <= MAX_PRINTF_LEN);
//
// Output to the debug terminal,
//
printf( "%s", OutputBuffer);
}
#endif // DBG