|
|
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
dhcp.c
Abstract:
This module contains DHCP specific utility routines used by the DHCP components.
Author:
Manny Weiser (mannyw) 12-Aug-1992
Revision History:
Madan Appiah (madana) 21-Oct-1992
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <dhcpl.h>
DWORD NTTimeToNTPTime(PULONG pTime, PFILETIME pft OPTIONAL);
DWORD NTPTimeToNTFileTime(PLONG pTime, PFILETIME pft, BOOL bHostOrder);
#undef DhcpAllocateMemory
#undef DhcpFreeMemory
PVOID DhcpAllocateMemory( DWORD Size ) /*++
Routine Description:
This function allocates the required size of memory by calling LocalAlloc.
Arguments:
Size - size of the memory block required.
Return Value:
Pointer to the allocated block.
--*/ {
ASSERT( Size != 0 );
return( LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size ) ); }
#undef DhcpFreeMemory
VOID DhcpFreeMemory( PVOID Memory ) /*++
Routine Description:
This function frees up the memory that was allocated by DhcpAllocateMemory.
Arguments:
Memory - pointer to the memory block that needs to be freed up.
Return Value:
none.
--*/ {
LPVOID Ptr;
ASSERT( Memory != NULL ); Ptr = LocalFree( Memory );
ASSERT( Ptr == NULL ); }
DATE_TIME DhcpCalculateTime( DWORD RelativeTime ) /*++
Routine Description:
The function calculates the absolute time of a time RelativeTime seconds from now.
Arguments:
RelativeTime - Relative time, in seconds.
Return Value:
The time in RelativeTime seconds from the current system time.
--*/ { SYSTEMTIME systemTime; ULONGLONG absoluteTime;
if( RelativeTime == INFINIT_LEASE ) { ((DATE_TIME *)&absoluteTime)->dwLowDateTime = DHCP_DATE_TIME_INFINIT_LOW; ((DATE_TIME *)&absoluteTime)->dwHighDateTime = DHCP_DATE_TIME_INFINIT_HIGH; } else {
GetSystemTime( &systemTime ); SystemTimeToFileTime( &systemTime, (FILETIME *)&absoluteTime );
absoluteTime = absoluteTime + RelativeTime * (ULONGLONG)10000000; }
return( *(DATE_TIME *)&absoluteTime ); }
DATE_TIME DhcpGetDateTime( VOID ) /*++
Routine Description:
This function returns FILETIME.
Arguments:
none.
Return Value:
FILETIME.
--*/ { SYSTEMTIME systemTime; DATE_TIME Time;
GetSystemTime( &systemTime ); SystemTimeToFileTime( &systemTime, (FILETIME *)&Time );
return( Time ); }
VOID DhcpNTToNTPTime( LPDATE_TIME AbsNTTime, DWORD Offset, PULONG NTPTimeStamp ) /*++
Routine Description:
The function calculates the absolute NTP timestamp from AbsTime on NT added by given offset.
Arguments:
AbsNTTime - AbsTime on NT. If 0, it will use current time.
RelativeOffset - offset to be added to AnsNTTime (in seconds.)
Return Value:
The time in RelativeTime seconds from the current system time.
--*/ { ULONGLONG LocalAbsNTTime; DWORD Error;
if ( AbsNTTime == 0 ) { GetSystemTimeAsFileTime((FILETIME *)&LocalAbsNTTime ); } else { LocalAbsNTTime = *(ULONGLONG *)AbsNTTime; }
// add offset
LocalAbsNTTime += Offset * (ULONGLONG)10000000;
// now convert to NT timestamp
Error = NTTimeToNTPTime( NTPTimeStamp, (PFILETIME)&LocalAbsNTTime );
DhcpAssert( ERROR_SUCCESS == Error ); return; }
VOID DhcpNTPToNTTime( PULONG NTPTimeStamp, DWORD Offset, DATE_TIME *NTTime ) /*++
Routine Description:
The function calculates the absolute NTP timestamp from AbsTime on NT added by given offset.
Arguments:
AbsNTTime - AbsTime on NT. If 0, it will use current time.
RelativeOffset - offset to be added to AnsNTTime (in seconds.)
Return Value:
The time in RelativeTime seconds from the current system time.
--*/ { ULONGLONG LocalAbsNTTime; DWORD Error;
Error = NTPTimeToNTFileTime( NTPTimeStamp, (FILETIME *)&LocalAbsNTTime, FALSE // not in host order.
);
DhcpAssert( ERROR_SUCCESS == Error );
// add offset
LocalAbsNTTime += Offset * (ULONGLONG)10000000;
// now convert to NT timestamp
// MBUG
*(ULONGLONG *)NTTime = LocalAbsNTTime; return; }
DWORD DhcpReportEventW( LPWSTR Source, DWORD EventID, DWORD EventType, DWORD NumStrings, DWORD DataLength, LPWSTR *Strings, LPVOID Data ) /*++
Routine Description:
This function writes the specified (EventID) log at the end of the eventlog.
Arguments:
Source - Points to a null-terminated string that specifies the name of the module referenced. The node must exist in the registration database, and the module name has the following format:
\EventLog\System\Lanmanworkstation
EventID - The specific event identifier. This identifies the message that goes with this event.
EventType - Specifies the type of event being logged. This parameter can have one of the following
values:
Value Meaning
EVENTLOG_ERROR_TYPE Error event EVENTLOG_WARNING_TYPE Warning event EVENTLOG_INFORMATION_TYPE Information event
NumStrings - Specifies the number of strings that are in the array at 'Strings'. A value of zero indicates no strings are present.
DataLength - Specifies the number of bytes of event-specific raw (binary) data to write to the log. If cbData is zero, no event-specific data is present.
Strings - Points to a buffer containing an array of null-terminated strings that are merged into the message before displaying to the user. This parameter must be a valid pointer (or NULL), even if cStrings is zero.
Data - Buffer containing the raw data. This parameter must be a valid pointer (or NULL), even if cbData is zero.
Return Value:
Returns the WIN32 extended error obtained by GetLastError().
NOTE : This function works slow since it calls the open and close eventlog source everytime.
--*/ { HANDLE EventlogHandle; DWORD ReturnCode;
//
// open eventlog section.
//
EventlogHandle = RegisterEventSourceW( NULL, Source );
if (EventlogHandle == NULL) {
ReturnCode = GetLastError(); goto Cleanup; }
//
// Log the error code specified
//
if( !ReportEventW( EventlogHandle, (WORD)EventType, 0, // event category
EventID, NULL, (WORD)NumStrings, DataLength, Strings, Data ) ) {
ReturnCode = GetLastError(); goto Cleanup; }
ReturnCode = NO_ERROR;
Cleanup:
if( EventlogHandle != NULL ) {
DeregisterEventSource(EventlogHandle); }
return ReturnCode; }
DWORD DhcpReportEventA( LPWSTR Source, DWORD EventID, DWORD EventType, DWORD NumStrings, DWORD DataLength, LPSTR *Strings, LPVOID Data ) /*++
Routine Description:
This function writes the specified (EventID) log at the end of the eventlog.
Arguments:
Source - Points to a null-terminated string that specifies the name of the module referenced. The node must exist in the registration database, and the module name has the following format:
\EventLog\System\Lanmanworkstation
EventID - The specific event identifier. This identifies the message that goes with this event.
EventType - Specifies the type of event being logged. This parameter can have one of the following
values:
Value Meaning
EVENTLOG_ERROR_TYPE Error event EVENTLOG_WARNING_TYPE Warning event EVENTLOG_INFORMATION_TYPE Information event
NumStrings - Specifies the number of strings that are in the array at 'Strings'. A value of zero indicates no strings are present.
DataLength - Specifies the number of bytes of event-specific raw (binary) data to write to the log. If cbData is zero, no event-specific data is present.
Strings - Points to a buffer containing an array of null-terminated strings that are merged into the message before displaying to the user. This parameter must be a valid pointer (or NULL), even if cStrings is zero.
Data - Buffer containing the raw data. This parameter must be a valid pointer (or NULL), even if cbData is zero.
Return Value:
Returns the WIN32 extended error obtained by GetLastError().
NOTE : This function works slow since it calls the open and close eventlog source everytime.
--*/ { HANDLE EventlogHandle; DWORD ReturnCode;
//
// open eventlog section.
//
EventlogHandle = RegisterEventSourceW( NULL, Source );
if (EventlogHandle == NULL) {
ReturnCode = GetLastError(); goto Cleanup; }
//
// Log the error code specified
//
if( !ReportEventA( EventlogHandle, (WORD)EventType, 0, // event category
EventID, NULL, (WORD)NumStrings, DataLength, Strings, Data ) ) {
ReturnCode = GetLastError(); goto Cleanup; }
ReturnCode = NO_ERROR;
Cleanup:
if( EventlogHandle != NULL ) {
DeregisterEventSource(EventlogHandle); }
return ReturnCode; }
DWORD DhcpLogUnknownOption( LPWSTR Source, DWORD EventID, LPOPTION Option ) /*++
Routine Description:
This routine logs an unknown DHCP option to event log.
Arguments:
Source - name of the app that logs this error. it should be either "DhcpClient" or "DhcpServer".
EventID - Event identifier number.
Option - pointer to the unknown option structure.
Return Value:
Windows Error code.
--*/ { LPWSTR Strings[2]; WCHAR StringsBuffer[ 2 * (3 + 1) ]; // for two string each is 1byte decimal number (0 - 255).
LPWSTR StringsPtr = StringsBuffer;
//
// convert option number.
//
Strings[0] = StringsPtr; DhcpDecimalToString( StringsPtr, Option->OptionType ); StringsPtr += 3;
*StringsPtr++ = L'\0';
//
// convert option length.
//
Strings[1] = StringsPtr; DhcpDecimalToString( StringsPtr, Option->OptionLength ); StringsPtr += 3;
*StringsPtr++ = L'\0';
//
// log error.
//
return( DhcpReportEventW( Source, EventID, EVENTLOG_WARNING_TYPE, 2, (DWORD)Option->OptionLength, Strings, (PVOID)Option->OptionValue ) ); }
#if DBG
VOID DhcpAssertFailed( LPSTR FailedAssertion, LPSTR FileName, DWORD LineNumber, LPSTR Message ) /*++
Routine Description:
Assertion failed.
Arguments:
FailedAssertion :
FileName :
LineNumber :
Message :
Return Value:
none.
--*/ { #ifndef DHCP_NOASSERT
RtlAssert( FailedAssertion, FileName, (ULONG) LineNumber, (PCHAR) Message); #endif
DhcpPrint(( 0, "Assert @ %s \n", FailedAssertion )); DhcpPrint(( 0, "Assert Filename, %s \n", FileName )); DhcpPrint(( 0, "Line Num. = %ld.\n", LineNumber )); DhcpPrint(( 0, "Message is %s\n", Message ));
}
#endif
LPWSTR DhcpRegIpAddressToKey( DHCP_IP_ADDRESS IpAddress, LPWSTR KeyBuffer ) /*++
Routine Description:
This function converts an IpAddress to registry key. The registry key is unicode string of IpAddress in dotted form.
Arguments:
IpAddress : IpAddress that needs conversion. The IpAddress is in host order.
KeyBuffer : pointer a buffer that will hold the converted registry key. The buffer should be big enough to converted key.
Return Value:
Pointer to the key the buffer.
--*/ { LPSTR OemKey; LPWSTR UnicodeKey; DWORD NetworkOrderIpAddress;
NetworkOrderIpAddress = htonl(IpAddress);
OemKey = inet_ntoa( *(struct in_addr *)&NetworkOrderIpAddress ); UnicodeKey = DhcpOemToUnicode( OemKey, KeyBuffer );
DhcpAssert( UnicodeKey == KeyBuffer );
return( UnicodeKey );
}
DHCP_IP_ADDRESS DhcpRegKeyToIpAddress( LPWSTR Key ) /*++
Routine Description:
This function converts registry key to Ip Address.
Arguments:
Key : Pointer to registry key.
Return Value:
Converted IpAddress.
--*/ { CHAR OemKeyBuffer[DHCP_IP_KEY_LEN]; LPSTR OemKey;
OemKey = DhcpUnicodeToOem( Key, OemKeyBuffer ); DhcpAssert( OemKey == OemKeyBuffer );
return( ntohl(inet_addr( OemKey )) ); }
LPWSTR DhcpRegOptionIdToKey( DHCP_OPTION_ID OptionId, LPWSTR KeyBuffer ) /*++
Routine Description:
This function converts an OptionId to registry key. The registry key is unicode string of OptionId, 3 unicode char. long and of the form L"000".
Arguments:
IpAddress : IpAddress that needs conversion.
KeyBuffer : pointer a buffer that will hold the converted registry key. The buffer should be at least 8 char. long.
Return Value:
Pointer to the key the buffer.
--*/
{ int i;
for (i = 2; i >= 0; i--) { KeyBuffer[i] = L'0' + (BYTE)(OptionId % 10 ); OptionId /= 10; } KeyBuffer[3] = L'\0';
return( KeyBuffer ); }
DHCP_OPTION_ID DhcpRegKeyToOptionId( LPWSTR Key ) /*++
Routine Description:
This function converts registry key to OptionId.
Arguments:
Key : Pointer to registry key.
Return Value:
Converted OptionId.
--*/
{ DHCP_OPTION_ID OptionId = 0; int i;
for (i = 0; i < 3 && Key[i] != L'\0'; i++) { OptionId = (OptionId * 10) + (Key[i] - L'0'); } return( OptionId ); }
DWORD DhcpStartWaitableTimer( HANDLE TimerHandle, DWORD SleepTime) /*++
Routine Description:
This routine starts the waitable timer. This timer fires off even when the system is in hibernate state.
Arguments
TimerHandle - Waitable Timer Handle
SleepTime - Sleep Time in seconds.
Return Value:
Status of the operation.
--*/ { DATE_TIME SleepTimeInNSec; // sleep time in nano seconds since Jan 1 1901
DWORD Error; BOOL Result;
Error = STATUS_SUCCESS; SleepTimeInNSec = DhcpCalculateTime( SleepTime );
Result = SetWaitableTimer( TimerHandle, // handle to timer object
(LARGE_INTEGER *)&SleepTimeInNSec, // due time.
0, // not periodic
NULL, // completion routine
NULL, // completion routine arg
TRUE // resume power state when due
); if ( !Result ) { DhcpPrint((0, "SetWaitableTimer reported Error = %d\n",Error=GetLastError())); } return Error; }
VOID DhcpCancelWaitableTimer( HANDLE TimerHandle ) /*++
Routine Description:
This routine cancels the waitable timer.
Arguments
TimerHandle - Waitable Timer Handle
Return Value:
--*/ { BOOL Result;
Result = CancelWaitableTimer( TimerHandle ); if ( !Result ) { DhcpPrint((0,"SetWaitableTimer reported Error = %lx\n",GetLastError())); } }
|