mirror of https://github.com/lianthony/NT4.0
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.
818 lines
18 KiB
818 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dhcp.c
|
|
|
|
Abstract:
|
|
|
|
This file contains utility functions.
|
|
|
|
Author:
|
|
|
|
Madan Appiah (madana) 7-Dec-1993.
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <dhcpcli.h>
|
|
#include <dhcploc.h>
|
|
#include <dhcppro.h>
|
|
|
|
typedef struct _POPUP_THREAD_PARAM {
|
|
LPWSTR Title;
|
|
LPWSTR Message;
|
|
} POPUP_THREAD_PARAM, *LPPOPUP_THREAD_PARAM;
|
|
|
|
POPUP_THREAD_PARAM PopupThreadParam = { NULL, NULL };
|
|
|
|
|
|
DWORD
|
|
DoPopup(
|
|
PVOID Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function pops up a message to the user. It must run it's own
|
|
thread. When the user acknowledge the popup, the thread deallocates
|
|
the message buffer and commits suicide.
|
|
|
|
Arguments:
|
|
|
|
Buffer - A pointer to a NULL terminated message buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD Result;
|
|
LPPOPUP_THREAD_PARAM Params = Buffer;
|
|
|
|
Result = MessageBox(
|
|
NULL,
|
|
Params->Message,
|
|
Params->Title,
|
|
MB_YESNO |
|
|
// MB_DEFBUTTON2 |
|
|
MB_ICONSTOP |
|
|
MB_SERVICE_NOTIFICATION |
|
|
MB_SYSTEMMODAL |
|
|
MB_SETFOREGROUND |
|
|
MB_DEFAULT_DESKTOP_ONLY );
|
|
|
|
|
|
LOCK_POPUP();
|
|
|
|
if( Params->Message != NULL ) {
|
|
LocalFree( Params->Message );
|
|
Params->Message = NULL;
|
|
}
|
|
|
|
if( Params->Title != NULL ) {
|
|
LocalFree( Params->Title );
|
|
Params->Title = NULL;
|
|
}
|
|
|
|
if( Result == IDYES ) {
|
|
|
|
//
|
|
// stop displaying messages in future.
|
|
//
|
|
|
|
DhcpGlobalDisplayPopup = TRUE;
|
|
}
|
|
else {
|
|
|
|
DhcpGlobalDisplayPopup = FALSE;
|
|
}
|
|
|
|
//
|
|
// close the global handle, so that we will not consume this thread
|
|
// resource until another popup.
|
|
//
|
|
|
|
CloseHandle( DhcpGlobalMsgPopupThreadHandle );
|
|
DhcpGlobalMsgPopupThreadHandle = NULL;
|
|
|
|
UNLOCK_POPUP();
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
DisplayUserMessage(
|
|
DWORD MessageId,
|
|
DHCP_IP_ADDRESS IpAddress,
|
|
time_t LeaseExpires
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function starts a new thread to display a message box.
|
|
|
|
Arguments:
|
|
|
|
MessageId - The ID of the message to display.
|
|
On NT, messages are attached to the TCPIP service DLL.
|
|
|
|
|
|
IpAddress - Ip address that could not be renewed.
|
|
|
|
LeaseExpires - Lease expires at.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD ThreadID;
|
|
LPWSTR Title = NULL;
|
|
DWORD TitleLength;
|
|
LPWSTR Message = NULL;
|
|
DWORD MsgLength;
|
|
LPSTR MessageParams[3];
|
|
LPSTR *MessageParamsPtr = NULL;
|
|
|
|
LPWSTR IPAddressString = NULL;
|
|
LPWSTR LeaseExpireString = NULL;
|
|
|
|
LOCK_POPUP();
|
|
|
|
//
|
|
// if we are asked to display no message popup, simply return.
|
|
//
|
|
|
|
if ( DhcpGlobalDisplayPopup == FALSE ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// if the message popup thread handle is non-null, check to see the
|
|
// thread is still running, if so don't display another popup,
|
|
// otherwise close the last popup handle and create another popup
|
|
// thread for new message.
|
|
//
|
|
|
|
if( DhcpGlobalMsgPopupThreadHandle != NULL ) {
|
|
|
|
DWORD WaitStatus;
|
|
|
|
//
|
|
// Time out immediately if the thread is still running.
|
|
//
|
|
|
|
WaitStatus = WaitForSingleObject(
|
|
DhcpGlobalMsgPopupThreadHandle,
|
|
0 );
|
|
|
|
if ( WaitStatus == WAIT_TIMEOUT ) {
|
|
goto Cleanup;
|
|
|
|
} else if ( WaitStatus == 0 ) {
|
|
|
|
//
|
|
// This shouldn't be a case, because we close this handle at
|
|
// the end of popup thread.
|
|
//
|
|
|
|
DhcpAssert( WaitStatus == 0 );
|
|
|
|
CloseHandle( DhcpGlobalMsgPopupThreadHandle );
|
|
DhcpGlobalMsgPopupThreadHandle = NULL;
|
|
|
|
} else {
|
|
DhcpPrint((
|
|
DEBUG_ERRORS,
|
|
"Cannot WaitFor message popup thread: %ld\n",
|
|
WaitStatus ));
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
|
|
switch (MessageId)
|
|
{
|
|
case MESSAGE_SUCCESSFUL_LEASE:
|
|
case MESSAGE_SUCCESSFUL_RENEW:
|
|
DhcpGlobalProtocolFailed = FALSE;
|
|
break;
|
|
|
|
case MESSAGE_FAILED_TO_RENEW_LEASE:
|
|
DhcpAssert( (IpAddress != (DWORD)-1) && (LeaseExpires != 0) );
|
|
DhcpGlobalProtocolFailed = TRUE;
|
|
break;
|
|
|
|
case MESSAGE_LEASE_TERMINATED:
|
|
DhcpAssert( (IpAddress != (DWORD)-1) );
|
|
DhcpGlobalProtocolFailed = TRUE;
|
|
break;
|
|
|
|
case MESSAGE_ADDRESS_CONFLICT:
|
|
DhcpGlobalProtocolFailed = TRUE;
|
|
DhcpAssert( IpAddress == (DWORD) -1 );
|
|
break;
|
|
}
|
|
|
|
|
|
if( (IpAddress != (DWORD)-1) || (LeaseExpires != 0) ) {
|
|
|
|
LPSTR *Ptr;
|
|
|
|
Ptr = MessageParams;
|
|
|
|
if(IpAddress != (DWORD)-1) {
|
|
IPAddressString =
|
|
DhcpOemToUnicode(
|
|
inet_ntoa(*(struct in_addr *)&IpAddress), NULL );
|
|
*Ptr = (PVOID)IPAddressString;
|
|
Ptr++;
|
|
}
|
|
|
|
if(LeaseExpires != 0) {
|
|
LeaseExpireString = DhcpOemToUnicode( ctime(&LeaseExpires), NULL );
|
|
|
|
//
|
|
// strip off the CR.
|
|
//
|
|
|
|
LeaseExpireString[wcslen(LeaseExpireString) - 1] = L'\0';
|
|
|
|
*Ptr = (PVOID)LeaseExpireString;
|
|
Ptr++;
|
|
}
|
|
|
|
*Ptr = NULL;
|
|
|
|
MessageParamsPtr = MessageParams;
|
|
}
|
|
|
|
MsgLength = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
(LPVOID)DhcpGlobalMessageFileHandle,
|
|
MessageId,
|
|
0, // language id.
|
|
(LPWSTR)&Message, // return buffer place holder.
|
|
0, // minimum buffer size to allocate.
|
|
(va_list *)MessageParamsPtr // insert strings.
|
|
);
|
|
|
|
if ( MsgLength == 0) {
|
|
DhcpPrint(( DEBUG_ERRORS,
|
|
"FormatMessage failed, err = %ld.\n", GetLastError()));
|
|
goto Cleanup;
|
|
}
|
|
|
|
DhcpAssert( Message != NULL );
|
|
DhcpAssert( (wcslen(Message)) == MsgLength );
|
|
|
|
//
|
|
// get message box title.
|
|
//
|
|
|
|
TitleLength = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
(LPVOID)DhcpGlobalMessageFileHandle,
|
|
MESSAGE_POPUP_TITLE,
|
|
0, // language id.
|
|
(LPWSTR)&Title, // return buffer place holder.
|
|
0, // minimum buffer size to allocate.
|
|
NULL // insert strings.
|
|
);
|
|
|
|
if ( TitleLength == 0) {
|
|
DhcpPrint(( DEBUG_ERRORS,
|
|
"FormatMessage to Message box Title failed, err = %ld.\n",
|
|
GetLastError()));
|
|
goto Cleanup;
|
|
}
|
|
|
|
DhcpAssert( Title != NULL );
|
|
DhcpAssert( (wcslen(Title)) == TitleLength );
|
|
|
|
PopupThreadParam.Title = Title;
|
|
PopupThreadParam.Message = Message;
|
|
|
|
//
|
|
// Create a thread, to display a message box to the user. We need
|
|
// a new thread because MessageBox() blocks until the user clicks
|
|
// on the OK button, and we can't block this thread.
|
|
//
|
|
// DoPopup frees the buffer.
|
|
//
|
|
|
|
DhcpGlobalMsgPopupThreadHandle = CreateThread(
|
|
NULL, // no security.
|
|
0, // default stack size.
|
|
DoPopup, // entry point.
|
|
(PVOID)&PopupThreadParam,
|
|
// parameter.
|
|
0, // create flag none.
|
|
&ThreadID
|
|
);
|
|
|
|
if ( DhcpGlobalMsgPopupThreadHandle == NULL ) {
|
|
DhcpPrint(( DEBUG_ERRORS,
|
|
"DisplayUserMessage: Could not create thread, err = %ld.\n",
|
|
GetLastError() ));
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if( IPAddressString != NULL ) {
|
|
DhcpFreeMemory( IPAddressString );
|
|
}
|
|
|
|
if( LeaseExpireString != NULL ) {
|
|
DhcpFreeMemory( LeaseExpireString );
|
|
}
|
|
|
|
UNLOCK_POPUP();
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
DhcpLogEvent(
|
|
PDHCP_CONTEXT DhcpContext,
|
|
DWORD EventNumber,
|
|
DWORD ErrorCode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions formats and writes an event log entry.
|
|
|
|
Arguments:
|
|
|
|
DhcpContext - The context for the event. Optional parameter.
|
|
|
|
EventNumber - The event to log.
|
|
|
|
ErrorCode - Windows Error code to record. Optional parameter.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
LPWSTR HWAddressBuffer = NULL;
|
|
LPWSTR IPAddressBuffer = NULL;
|
|
CHAR ErrorCodeOemStringBuf[32 + 1];
|
|
WCHAR ErrorCodeStringBuf[32 + 1];
|
|
LPWSTR ErrorCodeString = NULL;
|
|
LPWSTR Strings[10];
|
|
|
|
|
|
if( DhcpContext != NULL ) {
|
|
|
|
HWAddressBuffer =
|
|
DhcpAllocateMemory(
|
|
(DhcpContext->HardwareAddressLength * 2 + 1) *
|
|
sizeof(WCHAR) );
|
|
|
|
if( HWAddressBuffer == NULL ) {
|
|
DhcpPrint(( DEBUG_MISC, "Out of memory." ));
|
|
goto Cleanup;
|
|
}
|
|
|
|
DhcpHexToString(
|
|
HWAddressBuffer,
|
|
DhcpContext->HardwareAddress,
|
|
DhcpContext->HardwareAddressLength
|
|
);
|
|
|
|
HWAddressBuffer[DhcpContext->HardwareAddressLength * 2] = '\0';
|
|
|
|
IPAddressBuffer =
|
|
DhcpOemToUnicode(
|
|
inet_ntoa( *(struct in_addr *)&DhcpContext->IpAddress ),
|
|
NULL ); // allocate memory
|
|
|
|
if( IPAddressBuffer == NULL ) {
|
|
DhcpPrint(( DEBUG_MISC, "Out of memory." ));
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
|
|
strcpy( ErrorCodeOemStringBuf, "%%" );
|
|
_ultoa( ErrorCode, ErrorCodeOemStringBuf + 2, 10 );
|
|
|
|
ErrorCodeString = DhcpOemToUnicode(
|
|
ErrorCodeOemStringBuf,
|
|
ErrorCodeStringBuf );
|
|
|
|
//
|
|
// Log an event
|
|
//
|
|
|
|
switch ( EventNumber ) {
|
|
|
|
case EVENT_LEASE_TERMINATED:
|
|
|
|
DhcpAssert( HWAddressBuffer != NULL );
|
|
DhcpAssert( IPAddressBuffer != NULL );
|
|
|
|
Strings[0] = HWAddressBuffer;
|
|
Strings[1] = IPAddressBuffer;
|
|
|
|
DhcpReportEventW(
|
|
DHCP_EVENT_CLIENT,
|
|
EVENT_LEASE_TERMINATED,
|
|
EVENTLOG_ERROR_TYPE,
|
|
2,
|
|
0,
|
|
Strings,
|
|
NULL );
|
|
|
|
break;
|
|
|
|
case EVENT_FAILED_TO_OBTAIN_LEASE:
|
|
|
|
DhcpAssert( HWAddressBuffer != NULL );
|
|
DhcpAssert( ErrorCodeString != NULL );
|
|
|
|
Strings[0] = HWAddressBuffer;
|
|
Strings[1] = ErrorCodeString;
|
|
|
|
DhcpReportEventW(
|
|
DHCP_EVENT_CLIENT,
|
|
DhcpGlobalMultiHomedHost ?
|
|
EVENT_FAILED_TO_OBTAIN_LEASE_MULTI_HOME :
|
|
EVENT_FAILED_TO_OBTAIN_LEASE,
|
|
EVENTLOG_ERROR_TYPE,
|
|
2,
|
|
sizeof(ErrorCode),
|
|
Strings,
|
|
&ErrorCode );
|
|
|
|
break;
|
|
|
|
case EVENT_NACK_LEASE:
|
|
|
|
DhcpAssert( HWAddressBuffer != NULL );
|
|
DhcpAssert( IPAddressBuffer != NULL );
|
|
|
|
Strings[0] = IPAddressBuffer;
|
|
Strings[1] = HWAddressBuffer;
|
|
|
|
DhcpReportEventW(
|
|
DHCP_EVENT_CLIENT,
|
|
EVENT_NACK_LEASE,
|
|
EVENTLOG_ERROR_TYPE,
|
|
2,
|
|
0,
|
|
Strings,
|
|
NULL );
|
|
|
|
break;
|
|
|
|
case EVENT_ADDRESS_CONFLICT:
|
|
DhcpAssert( IPAddressBuffer != NULL );
|
|
DhcpAssert( HWAddressBuffer != NULL );
|
|
|
|
Strings[0] = IPAddressBuffer;
|
|
Strings[1] = HWAddressBuffer;
|
|
|
|
DhcpReportEventW(
|
|
DHCP_EVENT_CLIENT,
|
|
EVENT_ADDRESS_CONFLICT,
|
|
EVENTLOG_WARNING_TYPE,
|
|
2,
|
|
0,
|
|
Strings,
|
|
NULL );
|
|
break;
|
|
|
|
|
|
case EVENT_FAILED_TO_RENEW:
|
|
|
|
DhcpAssert( HWAddressBuffer != NULL );
|
|
DhcpAssert( ErrorCodeString != NULL );
|
|
|
|
Strings[0] = HWAddressBuffer;
|
|
Strings[1] = ErrorCodeString;
|
|
|
|
DhcpReportEventW(
|
|
DHCP_EVENT_CLIENT,
|
|
EVENT_FAILED_TO_RENEW,
|
|
EVENTLOG_WARNING_TYPE,
|
|
2,
|
|
sizeof(ErrorCode),
|
|
Strings,
|
|
&ErrorCode );
|
|
|
|
break;
|
|
|
|
case EVENT_DHCP_SHUTDOWN:
|
|
|
|
DhcpAssert( ErrorCodeString != NULL );
|
|
|
|
Strings[0] = ErrorCodeString;
|
|
|
|
DhcpReportEventW(
|
|
DHCP_EVENT_CLIENT,
|
|
EVENT_DHCP_SHUTDOWN,
|
|
EVENTLOG_WARNING_TYPE,
|
|
1,
|
|
sizeof(ErrorCode),
|
|
Strings,
|
|
&ErrorCode );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DhcpPrint(( DEBUG_MISC, "Unknown event." ));
|
|
break;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if( HWAddressBuffer != NULL ) {
|
|
DhcpFreeMemory( HWAddressBuffer );
|
|
}
|
|
|
|
if( IPAddressBuffer != NULL ) {
|
|
DhcpFreeMemory( IPAddressBuffer );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
#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;
|
|
static BeginningOfLine = TRUE;
|
|
LPSTR Text;
|
|
|
|
//
|
|
// If we aren't debugging this functionality, just return.
|
|
//
|
|
|
|
if ( DebugFlag != 0 && (DhcpGlobalDebugFlag & DebugFlag) == 0 ) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// vsprintf isn't multithreaded + we don't want to intermingle output
|
|
// from different threads.
|
|
//
|
|
|
|
// EnterCriticalSection( &DhcpGlobalDebugFileCritSect );
|
|
|
|
length = 0;
|
|
|
|
//
|
|
// Handle the beginning of a new line.
|
|
//
|
|
//
|
|
|
|
if ( BeginningOfLine ) {
|
|
|
|
length += (ULONG) sprintf( &OutputBuffer[length], "[Dhcp] " );
|
|
|
|
//
|
|
// Put the timestamp at the begining of the line.
|
|
//
|
|
IF_DEBUG( TIMESTAMP ) {
|
|
SYSTEMTIME SystemTime;
|
|
GetLocalTime( &SystemTime );
|
|
length += (ULONG) sprintf( &OutputBuffer[length],
|
|
"%02u/%02u %02u:%02u:%02u ",
|
|
SystemTime.wMonth,
|
|
SystemTime.wDay,
|
|
SystemTime.wHour,
|
|
SystemTime.wMinute,
|
|
SystemTime.wSecond );
|
|
}
|
|
|
|
//
|
|
// Indicate the type of message on the line
|
|
//
|
|
switch (DebugFlag) {
|
|
case DEBUG_ERRORS:
|
|
Text = "ERROR";
|
|
break;
|
|
|
|
case DEBUG_PROTOCOL:
|
|
Text = "PROTOCOL";
|
|
break;
|
|
|
|
case DEBUG_LEASE:
|
|
Text = "LEASE";
|
|
break;
|
|
|
|
case DEBUG_PROTOCOL_DUMP:
|
|
Text = "PROTOCOL_DUMP";
|
|
break;
|
|
|
|
case DEBUG_MISC:
|
|
Text = "MISC";
|
|
break;
|
|
|
|
default:
|
|
Text = NULL;
|
|
break;
|
|
}
|
|
|
|
if ( Text != NULL ) {
|
|
length += (ULONG) sprintf( &OutputBuffer[length], "[%s] ", Text );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Put a the information requested by the caller onto the line
|
|
//
|
|
|
|
va_start(arglist, Format);
|
|
|
|
length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
|
|
BeginningOfLine = (length > 0 && OutputBuffer[length-1] == '\n' );
|
|
|
|
va_end(arglist);
|
|
|
|
DhcpAssert(length <= MAX_PRINTF_LEN);
|
|
|
|
|
|
//
|
|
// Output to the debug terminal,
|
|
//
|
|
|
|
(void) DbgPrint( (PCH) OutputBuffer);
|
|
|
|
// LeaveCriticalSection( &DhcpGlobalDebugFileCritSect );
|
|
|
|
}
|
|
|
|
#endif // DBG
|
|
|
|
|
|
PDHCP_CONTEXT
|
|
FindDhcpContextOnRenewalList(
|
|
LPWSTR AdapterName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function finds the DHCP_CONTEXT for the specified
|
|
hardware address on the Renewal list.
|
|
|
|
This function must be called with LOCK_RENEW_LIST().
|
|
|
|
Arguments:
|
|
|
|
AdapterName - name of the adapter.
|
|
HardwareAddress - The hardware address to look for.
|
|
|
|
Return Value:
|
|
|
|
DHCP_CONTEXT - A pointer to the desired DHCP work context.
|
|
NULL - If the specified work context block cannot be found.
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY listEntry;
|
|
PDHCP_CONTEXT dhcpContext;
|
|
PLOCAL_CONTEXT_INFO LocalInfo;
|
|
|
|
listEntry = DhcpGlobalRenewList.Flink;
|
|
while ( listEntry != &DhcpGlobalRenewList ) {
|
|
dhcpContext = CONTAINING_RECORD( listEntry, DHCP_CONTEXT, RenewalListEntry );
|
|
|
|
LocalInfo = dhcpContext->LocalInformation;
|
|
if( _wcsicmp( LocalInfo->AdapterName, AdapterName ) == 0 ) {
|
|
return( dhcpContext );
|
|
}
|
|
|
|
listEntry = listEntry->Flink;
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
PDHCP_CONTEXT
|
|
FindDhcpContextOnNicList(
|
|
LPWSTR AdapterName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function finds the DHCP_CONTEXT for the specified
|
|
hardware address on the Work list.
|
|
|
|
This function must be called with LOCK_RENEW_LIST().
|
|
|
|
Arguments:
|
|
|
|
AdapterName - name of the adapter.
|
|
HardwareAddress - The hardware address to look for.
|
|
|
|
Return Value:
|
|
|
|
DHCP_CONTEXT - A pointer to the desired DHCP work context.
|
|
NULL - If the specified work context block cannot be found.
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY listEntry;
|
|
PDHCP_CONTEXT dhcpContext;
|
|
PLOCAL_CONTEXT_INFO LocalInfo;
|
|
|
|
listEntry = DhcpGlobalNICList.Flink;
|
|
while ( listEntry != &DhcpGlobalNICList ) {
|
|
dhcpContext = CONTAINING_RECORD( listEntry, DHCP_CONTEXT, NicListEntry );
|
|
|
|
LocalInfo = dhcpContext->LocalInformation;
|
|
if( _wcsicmp( LocalInfo->AdapterName, AdapterName ) == 0 ) {
|
|
return( dhcpContext );
|
|
}
|
|
|
|
listEntry = listEntry->Flink;
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsMultiHomeMachine(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function determines that this machine is multi-homed.
|
|
|
|
This function must be called with LOCK_RENEW_LIST().
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
TRUE : if this machine is multi homed.
|
|
FALSE : otherwise.
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY listEntry;
|
|
BOOL FirstAdapter = TRUE;
|
|
|
|
listEntry = DhcpGlobalNICList.Flink;
|
|
while ( listEntry != &DhcpGlobalNICList ) {
|
|
|
|
//
|
|
// if this is not first adapter then this machine machine must
|
|
// be multi-homed.
|
|
//
|
|
|
|
if ( !FirstAdapter ) {
|
|
return( TRUE );
|
|
}
|
|
|
|
FirstAdapter = FALSE;
|
|
listEntry = listEntry->Flink;
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|