5329 lines
128 KiB
C
5329 lines
128 KiB
C
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dhcstub.c
|
|
|
|
Abstract:
|
|
|
|
Client stubs of the DHCP server service APIs.
|
|
|
|
Author:
|
|
|
|
Madan Appiah (madana) 10-Sep-1993
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "dhcpcli.h"
|
|
#include <dhcpds.h> // this is from dhcpds directory
|
|
#include <stdlib.h>
|
|
#include <winsock2.h>
|
|
#include <rpcasync.h>
|
|
|
|
CRITICAL_SECTION DhcpsapiDllCritSect;
|
|
|
|
static DWORD Initialized = 0;
|
|
static DWORD TlsIndex = 0xFFFFFFFF;
|
|
|
|
|
|
BOOLEAN
|
|
DhcpStubsDllInit (
|
|
IN PVOID DllHandle,
|
|
IN ULONG Reason,
|
|
IN PCONTEXT Context OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the DLL initialization routine for dhcpsapi.dll.
|
|
|
|
Arguments:
|
|
|
|
Standard.
|
|
|
|
Return Value:
|
|
|
|
TRUE iff initialization succeeded.
|
|
|
|
--*/
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
BOOL BoolError;
|
|
DWORD Length;
|
|
|
|
UNREFERENCED_PARAMETER(DllHandle); // avoid compiler warnings
|
|
UNREFERENCED_PARAMETER(Context); // avoid compiler warnings
|
|
|
|
//
|
|
// Handle attaching netlogon.dll to a new process.
|
|
//
|
|
|
|
if (Reason == DLL_PROCESS_ATTACH) {
|
|
|
|
if ( !DisableThreadLibraryCalls( DllHandle ) ) {
|
|
return( FALSE );
|
|
}
|
|
|
|
try {
|
|
|
|
InitializeCriticalSection(&DhcpsapiDllCritSect);
|
|
|
|
} except ( I_RpcExceptionFilter(RpcExceptionCode())) {
|
|
|
|
Error = GetLastError( );
|
|
return FALSE;
|
|
}
|
|
|
|
} else if (Reason == DLL_PROCESS_DETACH) {
|
|
|
|
DeleteCriticalSection(&DhcpsapiDllCritSect);
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
VOID _cdecl
|
|
DbgPrint( char *, ... );
|
|
|
|
LPWSTR _inline
|
|
DhcpOemToUnicode( // convert from ansi buffer to uni buffer
|
|
IN LPSTR Ansi,
|
|
IN OUT LPWSTR Unicode
|
|
)
|
|
{
|
|
if( NULL == Unicode || NULL == Ansi ) { // should not happen
|
|
return NULL;
|
|
}
|
|
|
|
if( -1 == mbstowcs(Unicode, Ansi, 1+strlen(Ansi))) {
|
|
return NULL;
|
|
}
|
|
return Unicode;
|
|
}
|
|
|
|
|
|
//DOC DhcpDsInit must be called exactly once per process.. this initializes the
|
|
//DOC memory and other structures for this process. This initializes some DS
|
|
//DOC object handles (memory), and hence is slow as this has to read from DS.
|
|
DWORD
|
|
DhcpDsInit(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD Err = NO_ERROR;
|
|
|
|
EnterCriticalSection(&DhcpsapiDllCritSect);
|
|
|
|
do {
|
|
|
|
if( 0 != Initialized ) {
|
|
break;
|
|
}
|
|
|
|
TlsIndex = TlsAlloc();
|
|
if( 0xFFFFFFFF == TlsIndex ) {
|
|
Err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
Err = DhcpDsInitDS(0, NULL);
|
|
if( ERROR_SUCCESS != Err ) {
|
|
TlsFree(TlsIndex);
|
|
TlsIndex = 0xFFFFFFFF;
|
|
}
|
|
|
|
break;
|
|
} while ( 0 );
|
|
|
|
if( NO_ERROR == Err ) Initialized ++;
|
|
|
|
LeaveCriticalSection(&DhcpsapiDllCritSect);
|
|
return Err;
|
|
}
|
|
|
|
//DOC DhcpDsCleanup undoes the effect of any DhcpDsInit. This function should be
|
|
//DOC called exactly once for each process, and only at termination. Note that
|
|
//DOC it is safe to call this function even if DhcpDsInit does not succeed.
|
|
VOID
|
|
DhcpDsCleanup(
|
|
VOID
|
|
)
|
|
{
|
|
EnterCriticalSection(&DhcpsapiDllCritSect);
|
|
|
|
do {
|
|
if( 0 == Initialized ) break;
|
|
Initialized --;
|
|
if( 0 != Initialized ) break;
|
|
|
|
TlsFree(TlsIndex);
|
|
DhcpDsCleanupDS();
|
|
TlsIndex = 0xFFFFFFFF;
|
|
|
|
} while ( 0 );
|
|
|
|
LeaveCriticalSection(&DhcpsapiDllCritSect);
|
|
}
|
|
|
|
#define DHCP_FLAGS_DONT_ACCESS_DS 0x01
|
|
#define DHCP_FLAGS_DONT_DO_RPC 0x02
|
|
|
|
//DOC DhcpSetThreadOptions currently allows only one option to be set. This is the
|
|
//DOC flag DHCP_FLAGS_DONT_ACCESS_DS. This affects only the current executing thread.
|
|
//DOC When this function is executed, all calls made further DONT access the registry,
|
|
//DOC excepting the DhcpEnumServers, DhcpAddServer and DhcpDeleteServer calls.
|
|
DWORD
|
|
DhcpSetThreadOptions( // set options for current thread
|
|
IN DWORD Flags, // options, currently 0 or DHCP_FLAGS_DONT_ACCESS_DS
|
|
IN LPVOID Reserved // must be NULL, reserved for future
|
|
)
|
|
{
|
|
BOOL Err;
|
|
|
|
Err = TlsSetValue(TlsIndex, ULongToPtr(Flags));
|
|
if( FALSE == Err ) { // could not set the value?
|
|
return GetLastError();
|
|
}
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//DOC DhcpGetThreadOptions retrieves the current thread options as set by DhcpSetThreadOptions.
|
|
//DOC If none were set, the return value is zero.
|
|
DWORD
|
|
DhcpGetThreadOptions( // get current thread options
|
|
OUT LPDWORD pFlags, // this DWORD is filled with current optiosn..
|
|
IN OUT LPVOID Reserved // must be NULL, reserved for future
|
|
)
|
|
{
|
|
if( NULL == pFlags ) return ERROR_INVALID_PARAMETER;
|
|
*pFlags = (DWORD)((DWORD_PTR)TlsGetValue(TlsIndex));
|
|
if( 0 == *pFlags ) return GetLastError(); // dont know if there were no options or error
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//DOC DontAccessDs is an inline that checks to see if requested NOT to access DS ..
|
|
BOOL _inline // TRUE ==> Dont access DS.
|
|
DontAccessDs( // check to see if requested NOT to access DS
|
|
VOID
|
|
)
|
|
{
|
|
DWORD Flags;
|
|
|
|
if( CFLAG_DONT_DO_DSWORK ) return TRUE; // if DS is turned off return TRUE immediately..
|
|
|
|
Flags = (DWORD)((DWORD_PTR)TlsGetValue(TlsIndex)); // dont bother if it fails, as this would be 0 then.
|
|
return (Flags & DHCP_FLAGS_DONT_ACCESS_DS)? TRUE : FALSE;
|
|
}
|
|
|
|
//DOC DontDoRPC is an inline that checks to see if requested NOT to do RPC (maybe only DS)..
|
|
BOOL _inline // TRUE ==> Dont do RPC
|
|
DontDoRPC( // check to see if requested not to do RPC
|
|
VOID
|
|
)
|
|
{
|
|
DWORD Flags;
|
|
Flags = (DWORD)((DWORD_PTR)TlsGetValue(TlsIndex)); // dont bother if it fails, as this would be 0 then.
|
|
return (Flags & DHCP_FLAGS_DONT_DO_RPC)? TRUE : FALSE;
|
|
}
|
|
|
|
//
|
|
// API proto types
|
|
//
|
|
|
|
//
|
|
// Subnet APIs
|
|
//
|
|
|
|
DWORD
|
|
DhcpCreateSubnet(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
LPDHCP_SUBNET_INFO SubnetInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates a new subnet structure in the server
|
|
registry database. The server will start managing the new subnet
|
|
and distribute IP address to clients from that subnet. However
|
|
the administrator should call DhcpAddSubnetElement() to add an
|
|
address range for distribution. The PrimaryHost field specified in
|
|
the SubnetInfo should be same as the server pointed by
|
|
ServerIpAddress.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server (Primary).
|
|
|
|
SubnetAddress : IP Address of the new subnet.
|
|
|
|
SubnetInfo : Pointer to the new subnet information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_EXISTS - if the subnet is already managed.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains an
|
|
inconsistent fields.
|
|
|
|
other WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpCreateSubnet(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
SubnetInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpCreateSubnetDS(ServerIpAddress, SubnetAddress, SubnetInfo);
|
|
}
|
|
|
|
DWORD
|
|
DhcpSetSubnetInfo(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
LPDHCP_SUBNET_INFO SubnetInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets the information fields of the subnet that is already
|
|
managed by the server. The valid fields that can be modified are 1.
|
|
SubnetName, 2. SubnetComment, 3. PrimaryHost.NetBiosName and 4.
|
|
PrimaryHost.HostName. Other fields can't be modified.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
SubnetInfo : Pointer to the subnet information structure.
|
|
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
Other WINDOWS errors.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpSetSubnetInfo(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
SubnetInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetSubnetInfoDS(ServerIpAddress, SubnetAddress, SubnetInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetSubnetInfo(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
LPDHCP_SUBNET_INFO *SubnetInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the information of the subnet managed by
|
|
the server.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
SubnetInfo : Pointer to a location where the subnet information
|
|
structure pointer is returned. Caller should free up
|
|
this buffer after use by calling DhcpRPCFreeMemory().
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
Other WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetSubnetInfo(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
SubnetInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetSubnetInfoDS(ServerIpAddress, SubnetAddress, SubnetInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpEnumSubnets(
|
|
DHCP_CONST WCHAR *ServerIpAddress,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_IP_ARRAY *EnumInfo,
|
|
DWORD *ElementsRead,
|
|
DWORD *ElementsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enumerates the available subnets.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to
|
|
zero on first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
EnumInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up the buffer after use
|
|
by calling DhcpRPCFreeMemory().
|
|
|
|
ElementsRead : Pointer to a DWORD where the number of subnet
|
|
elements in the above buffer is returned.
|
|
|
|
ElementsTotal : Pointer to a DWORD where the total number of
|
|
elements remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumSubnets(
|
|
ServerIpAddress,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
EnumInfo,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpEnumSubnetsDS(
|
|
ServerIpAddress, ResumeHandle, PreferredMaximum, EnumInfo, ElementsRead, ElementsTotal
|
|
);
|
|
}
|
|
|
|
DWORD
|
|
DhcpAddSubnetElement(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
LPDHCP_SUBNET_ELEMENT_DATA AddElementInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function adds a enumerable type of subnet elements to the
|
|
specified subnet. The new elements that are added to the subnet will
|
|
come into effect immediately.
|
|
|
|
NOTE: It is not clear now how do we handle the new secondary hosts.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
AddElementInfo : Pointer to an element information structure
|
|
containing new element that is added to the subnet.
|
|
DhcpIPClusters element type is invalid to specify.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains invalid
|
|
data.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpAddSubnetElement(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
AddElementInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpAddSubnetElementDS(ServerIpAddress, SubnetAddress, AddElementInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpEnumSubnetElements(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY *EnumElementInfo,
|
|
DWORD *ElementsRead,
|
|
DWORD *ElementsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enumerates the eumerable fields of a subnet.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
EnumElementType : Type of the subnet element that are enumerated.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to
|
|
zero on first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
EnumElementInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up the buffer after use
|
|
by calling DhcpRPCFreeMemory().
|
|
|
|
ElementsRead : Pointer to a DWORD where the number of subnet
|
|
elements in the above buffer is returned.
|
|
|
|
ElementsTotal : Pointer to a DWORD where the total number of
|
|
elements remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumSubnetElements(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
EnumElementType,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
EnumElementInfo,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpEnumSubnetElementsDS(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
EnumElementType,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
EnumElementInfo,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
}
|
|
|
|
DWORD
|
|
DhcpRemoveSubnetElement(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
LPDHCP_SUBNET_ELEMENT_DATA RemoveElementInfo,
|
|
DHCP_FORCE_FLAG ForceFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a subnet element from managing. If the subnet
|
|
element is in use (for example, if the IpRange is in use) then it
|
|
returns error according to the ForceFlag specified.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
RemoveElementInfo : Pointer to an element information structure
|
|
containing element that should be removed from the subnet.
|
|
DhcpIPClusters element type is invalid to specify.
|
|
|
|
ForceFlag - Indicates how forcefully this element is removed.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains invalid
|
|
data.
|
|
|
|
DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
|
|
reason it is has been used.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpRemoveSubnetElement(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
RemoveElementInfo,
|
|
ForceFlag
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpRemoveSubnetElementDS(ServerIpAddress, SubnetAddress, RemoveElementInfo,ForceFlag);
|
|
}
|
|
|
|
DWORD
|
|
DhcpDeleteSubnet(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_FORCE_FLAG ForceFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a subnet from DHCP server management. If the
|
|
subnet is in use (for example, if the IpRange is in use)
|
|
then it returns error according to the ForceFlag specified.
|
|
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
ForceFlag - Indicates how forcefully this element is removed.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains invalid
|
|
data.
|
|
|
|
DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
|
|
reason it is has been used.
|
|
|
|
Other WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpDeleteSubnet(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
ForceFlag
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpDeleteSubnetDS(ServerIpAddress,SubnetAddress,ForceFlag);
|
|
}
|
|
|
|
//
|
|
// Option APIs
|
|
//
|
|
|
|
DWORD
|
|
DhcpCreateOption(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_OPTION_ID OptionID,
|
|
LPDHCP_OPTION OptionInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates a new option that will be managed by the
|
|
server. The optionID specified the ID of the new option, it should
|
|
be within 0-255 range. If no default value is specified for this
|
|
option, then this API automatically adds a default value from RFC
|
|
1122 doc. (if it is defined).
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
OptionID : The ID of the new option.
|
|
|
|
OptionInfo : Pointer to new option information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_EXISTS - if the option exists already.
|
|
|
|
other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpCreateOption(
|
|
ServerIpAddress,
|
|
OptionID,
|
|
OptionInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpCreateOptionDS(ServerIpAddress,OptionID, OptionInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpSetOptionInfo(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_OPTION_ID OptionID,
|
|
LPDHCP_OPTION OptionInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions sets the Options information fields.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
OptionID : The ID of the option to be set.
|
|
|
|
OptionInfo : Pointer to new option information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
|
|
|
|
other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpSetOptionInfo(
|
|
ServerIpAddress,
|
|
OptionID,
|
|
OptionInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetOptionInfoDS(ServerIpAddress, OptionID, OptionInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetOptionInfo(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_OPTION_ID OptionID,
|
|
LPDHCP_OPTION *OptionInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the current information structure of the specified
|
|
option.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
OptionID : The ID of the option to be retrieved.
|
|
|
|
OptionInfo : Pointer to a location where the retrieved option
|
|
structure pointer is returned. Caller should free up
|
|
the buffer after use by calling DhcpRPCFreeMemory().
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
|
|
|
|
other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetOptionInfo(
|
|
ServerIpAddress,
|
|
OptionID,
|
|
OptionInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetOptionInfoDS(ServerIpAddress, OptionID, OptionInfo);
|
|
}
|
|
|
|
DWORD
|
|
DhcpEnumOptions(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_OPTION_ARRAY *Options,
|
|
DWORD *OptionsRead,
|
|
DWORD *OptionsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions retrieves the information of all known options.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to
|
|
zero on first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
Options : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up this buffer
|
|
after use by calling DhcpRPCFreeMemory().
|
|
|
|
OptionsRead : Pointer to a DWORD where the number of options
|
|
in the above buffer is returned.
|
|
|
|
OptionsTotal : Pointer to a DWORD where the total number of
|
|
options remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
|
|
|
|
other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumOptions(
|
|
ServerIpAddress,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
Options,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
|
|
return DhcpEnumOptions(
|
|
ServerIpAddress,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
Options,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpRemoveOption(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_OPTION_ID OptionID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes the specified option from the server database.
|
|
Also it browses through the Global/Subnet/ReservedIP
|
|
option lists and deletes them too (?? This will be too expensive.).
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
OptionID : The ID of the option to be removed.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
|
|
|
|
other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpRemoveOption(
|
|
ServerIpAddress,
|
|
OptionID
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpRemoveOptionDS(ServerIpAddress, OptionID);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpSetOptionValue(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_OPTION_ID OptionID,
|
|
LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
LPDHCP_OPTION_DATA OptionValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function sets a new option value at the specified scope. If
|
|
there is already a value available for the specified option at
|
|
specified scope then this function will replace it otherwise it will
|
|
create a new entry at that scope.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
OptionID : The ID of the option whose value should be set.
|
|
|
|
ScopeInfo : Pointer to the scope information structure.
|
|
|
|
OptionValue : Pointer to the option value structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option is unknown.
|
|
|
|
ERROR_INVALID_PARAMETER - if the scope information specified is invalid.
|
|
|
|
other WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpSetOptionValue(
|
|
ServerIpAddress,
|
|
OptionID,
|
|
ScopeInfo,
|
|
OptionValue
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetOptionValueDS(ServerIpAddress,OptionID,ScopeInfo,OptionValue);
|
|
}
|
|
|
|
DWORD
|
|
DhcpSetOptionValues(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
LPDHCP_OPTION_VALUE_ARRAY OptionValues
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function sets a set of new options value at the specified scope.
|
|
If there is already a value available for the specified option at
|
|
specified scope then this function will replace it otherwise it will
|
|
create a new entry at that scope.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ScopeInfo : Pointer to the scope information structure.
|
|
|
|
OptionValue : Pointer to the option value structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option is unknown.
|
|
|
|
ERROR_INVALID_PARAMETER - if the scope information specified is invalid.
|
|
|
|
other WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpSetOptionValues(
|
|
ServerIpAddress,
|
|
ScopeInfo,
|
|
OptionValues
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetOptionValuesDS(ServerIpAddress,ScopeInfo,OptionValues);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetOptionValue(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_OPTION_ID OptionID,
|
|
LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
LPDHCP_OPTION_VALUE *OptionValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the current option value at the specified
|
|
scope. It returns error if there is no option value is available at
|
|
the specified scope.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
OptionID : The ID of the option whose value is returned.
|
|
|
|
ScopeInfo : Pointer to the scope information structure.
|
|
|
|
OptionValue : Pointer to a location where the pointer to the option
|
|
value structure is returned. Caller should free up this buffer
|
|
after use by calling DhcpRPCFreeMemory().
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option is unknown.
|
|
|
|
ERROR_DHCP_NO_OPTION_VALUE - if no the option value is available at
|
|
the specified scope.
|
|
|
|
other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetOptionValue(
|
|
ServerIpAddress,
|
|
OptionID,
|
|
ScopeInfo,
|
|
OptionValue
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetOptionValueDS(
|
|
ServerIpAddress,
|
|
OptionID,
|
|
ScopeInfo,
|
|
OptionValue
|
|
);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpEnumOptionValues(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_OPTION_VALUE_ARRAY *OptionValues,
|
|
DWORD *OptionsRead,
|
|
DWORD *OptionsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enumerates the available options values at the
|
|
specified scope.
|
|
|
|
Arguments:
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ScopeInfo : Pointer to the scope information structure.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to
|
|
zero on first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
OptionValues : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up this buffer
|
|
after use by calling DhcpRPCFreeMemory().
|
|
|
|
OptionsRead : Pointer to a DWORD where the number of options
|
|
in the above buffer is returned.
|
|
|
|
OptionsTotal : Pointer to a DWORD where the total number of
|
|
options remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SCOPE_NOT_PRESENT - if the scope is unknown.
|
|
|
|
ERROR_MORE_DATA - if more options available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more option to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumOptionValues(
|
|
ServerIpAddress,
|
|
ScopeInfo,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
OptionValues,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpEnumOptionValuesDS(
|
|
ServerIpAddress,
|
|
ScopeInfo,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
OptionValues,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpRemoveOptionValue(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_OPTION_ID OptionID,
|
|
LPDHCP_OPTION_SCOPE_INFO ScopeInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes the specified option from specified scope.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
OptionID : The ID of the option to be removed.
|
|
|
|
ScopeInfo : Pointer to the scope information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
|
|
|
|
other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpRemoveOptionValue(
|
|
ServerIpAddress,
|
|
OptionID,
|
|
ScopeInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpRemoveOptionValueDS(ServerIpAddress,OptionID,ScopeInfo);
|
|
|
|
}
|
|
|
|
//
|
|
// Client APIs
|
|
//
|
|
|
|
DWORD
|
|
DhcpCreateClientInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_CLIENT_INFO ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates a client record in server's database. Also
|
|
this marks the specified client IP address as unavailable (or
|
|
distributed). This function returns error under the following cases :
|
|
|
|
1. If the specified client IP address is not within the server
|
|
management.
|
|
|
|
2. If the specified client IP address is already unavailable.
|
|
|
|
3. If the specified client record is already in the server's
|
|
database.
|
|
|
|
This function may be used to distribute IP addresses manually.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ClientInfo : Pointer to the client information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_IP_ADDRESS_NOT_MANAGED - if the specified client
|
|
IP address is not managed by the server.
|
|
|
|
ERROR_DHCP_IP_ADDRESS_NOT_AVAILABLE - if the specified client IP
|
|
address is not available. May be in use by some other client.
|
|
|
|
ERROR_DHCP_CLIENT_EXISTS - if the client record exists already in
|
|
server's database.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpCreateClientInfo(
|
|
ServerIpAddress,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpSetClientInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_CLIENT_INFO ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets client information record on the server's
|
|
database.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ClientInfo : Pointer to the client information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
|
|
not exist on the server's database.
|
|
|
|
ERROR_INVALID_PARAMETER - if the client information structure
|
|
contains inconsistent data.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpSetClientInfo(
|
|
ServerIpAddress,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_SUCCESS;
|
|
return DhcpSetClientInfoDS(ServerIpAddress, ClientInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetClientInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_SEARCH_INFO SearchInfo,
|
|
LPDHCP_CLIENT_INFO *ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves client information record from the server's
|
|
database.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SearchInfo : Pointer to a search information record which is the key
|
|
for the client's record search.
|
|
|
|
ClientInfo : Pointer to a location where the pointer to the client
|
|
information structure is returned. This caller should free up
|
|
this buffer after use by calling DhcpRPCFreeMemory().
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
|
|
not exist on the server's database.
|
|
|
|
ERROR_INVALID_PARAMETER - if the search information invalid.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetClientInfo(
|
|
ServerIpAddress,
|
|
SearchInfo,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetClientInfoDS(ServerIpAddress, SearchInfo, ClientInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpDeleteClientInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_SEARCH_INFO ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function deletes the specified client record. Also it frees up
|
|
the client IP address for redistribution.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ClientInfo : Pointer to a client information which is the key for
|
|
the client's record search.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
|
|
not exist on the server's database.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpDeleteClientInfo(
|
|
ServerIpAddress,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpEnumSubnetClients(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_CLIENT_INFO_ARRAY *ClientInfo,
|
|
DWORD *ClientsRead,
|
|
DWORD *ClientsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns all registered clients of the specified
|
|
subnet.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to zero on
|
|
first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
ClientInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up this buffer
|
|
after use by calling DhcpRPCFreeMemory().
|
|
|
|
ClientsRead : Pointer to a DWORD where the number of clients
|
|
that in the above buffer is returned.
|
|
|
|
ClientsTotal : Pointer to a DWORD where the total number of
|
|
clients remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumSubnetClients(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
ClientInfo,
|
|
ClientsRead,
|
|
ClientsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetClientOptions(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS ClientIpAddress,
|
|
DHCP_IP_MASK ClientSubnetMask,
|
|
LPDHCP_OPTION_LIST *ClientOptions
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the options that are given to the
|
|
specified client on boot request.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ClientIpAddress : IP Address of the client whose options to be
|
|
retrieved
|
|
|
|
ClientSubnetMask : Subnet mask of the client.
|
|
|
|
ClientOptions : Pointer to a location where the retrieved option
|
|
structure pointer is returned. Caller should free up
|
|
the buffer after use by calling DhcpRPCFreeMemory().
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the specified client subnet is
|
|
not managed by the server.
|
|
|
|
ERROR_DHCP_IP_ADDRESS_NOT_MANAGED - if the specified client
|
|
IP address is not managed by the server.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetClientOptions(
|
|
ServerIpAddress,
|
|
ClientIpAddress,
|
|
ClientSubnetMask,
|
|
ClientOptions
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetMibInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_MIB_INFO *MibInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves all counter values of the DHCP server
|
|
service.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
MibInfo : pointer a counter/table buffer. Caller should free up this
|
|
buffer after usage.
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetMibInfo(
|
|
ServerIpAddress,
|
|
MibInfo );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpServerSetConfig(
|
|
LPWSTR ServerIpAddress,
|
|
DWORD FieldsToSet,
|
|
LPDHCP_SERVER_CONFIG_INFO ConfigInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets the DHCP server configuration information.
|
|
Serveral of the configuration information will become effective
|
|
immediately.
|
|
|
|
The following parameters require restart of the service after this
|
|
API is called successfully.
|
|
|
|
Set_APIProtocolSupport
|
|
Set_DatabaseName
|
|
Set_DatabasePath
|
|
Set_DatabaseLoggingFlag
|
|
Set_RestoreFlag
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
FieldsToSet : Bit mask of the fields in the ConfigInfo structure to
|
|
be set.
|
|
|
|
ConfigInfo: Pointer to the info structure to be set.
|
|
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpServerSetConfig(
|
|
ServerIpAddress,
|
|
FieldsToSet,
|
|
ConfigInfo );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpServerGetConfig(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_SERVER_CONFIG_INFO *ConfigInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the current configuration information of the
|
|
server.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ConfigInfo: Pointer to a location where the pointer to the dhcp
|
|
server config info structure is returned. Caller should free up
|
|
this structure after use.
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpServerGetConfig(
|
|
ServerIpAddress,
|
|
ConfigInfo );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpScanDatabase(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DWORD FixFlag,
|
|
LPDHCP_SCAN_LIST *ScanList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function scans the database entries and registry bit-map for
|
|
specified subnet scope and veryfies to see they match. If they
|
|
don't match, this api will return the list of inconsistent entries.
|
|
Optionally FixFlag can be used to fix the bad entries.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : Address of the subnet scope to verify.
|
|
|
|
FixFlag : If this flag is TRUE, this api will fix the bad entries.
|
|
|
|
ScanList : List of bad entries returned. The caller should free up
|
|
this memory after it has been used.
|
|
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpScanDatabase(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
FixFlag,
|
|
ScanList );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetVersion(
|
|
LPWSTR ServerIpAddress,
|
|
LPDWORD MajorVersion,
|
|
LPDWORD MinorVersion
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the major and minor version numbers of the
|
|
server.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
MajorVersion : pointer to a location where the major version of the
|
|
server is returned.
|
|
|
|
MinorVersion : pointer to a location where the minor version of the
|
|
server is returned.
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetVersion(
|
|
ServerIpAddress,
|
|
MajorVersion,
|
|
MinorVersion );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
DhcpRpcFreeMemory(
|
|
PVOID BufferPointer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function deallocates the memory that was alloted by the RPC and
|
|
given to the client as part of the retrun info structures.
|
|
|
|
Arguments:
|
|
|
|
BufferPointer : pointer to a memory block that is deallocated.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
MIDL_user_free( BufferPointer );
|
|
}
|
|
|
|
#if 0
|
|
DWORD
|
|
DhcpGetVersion(
|
|
LPWSTR ServerIpAddress,
|
|
LPDWORD MajorVersion,
|
|
LPDWORD MinorVersion
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the major and minor version numbers of the
|
|
server.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
MajorVersion : pointer to a location where the major version of the
|
|
server is returned.
|
|
|
|
MinorVersion : pointer to a location where the minor version of the
|
|
server is returned.
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Error;
|
|
handle_t BindingHandle = NULL;
|
|
RPC_IF_ID_VECTOR *InterfaceIdVectors = NULL;
|
|
DWORD i;
|
|
|
|
//
|
|
// take a copy of the global client if handle structure (which is read
|
|
// only) to modify.
|
|
//
|
|
|
|
RPC_CLIENT_INTERFACE ClientIf =
|
|
*((RPC_CLIENT_INTERFACE *)dhcpsrv_ClientIfHandle);
|
|
|
|
//
|
|
// bind to the server.
|
|
//
|
|
|
|
BindingHandle = DHCP_SRV_HANDLE_bind( ServerIpAddress );
|
|
|
|
if( BindingHandle == NULL ) {
|
|
Error = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// loop to match the version of the server. We handle only minor
|
|
// versions.
|
|
//
|
|
|
|
for (;;) {
|
|
|
|
Error = RpcEpResolveBinding(
|
|
BindingHandle,
|
|
(RPC_IF_HANDLE)&ClientIf );
|
|
|
|
if( Error == RPC_S_OK ) {
|
|
break;
|
|
}
|
|
|
|
if( Error != EPT_S_NOT_REGISTERED ){
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// decrement minor version number and try again, until version
|
|
// becomes 0.
|
|
//
|
|
|
|
if( ClientIf.InterfaceId.SyntaxVersion.MinorVersion != 0 ) {
|
|
|
|
ClientIf.InterfaceId.SyntaxVersion.MinorVersion--;
|
|
}
|
|
else {
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Error = RpcMgmtInqIfIds(
|
|
BindingHandle,
|
|
&InterfaceIdVectors );
|
|
|
|
if( Error != RPC_S_OK ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// match uuid.
|
|
//
|
|
|
|
for( i = 0; i < InterfaceIdVectors->Count; i++) {
|
|
|
|
RPC_STATUS Result;
|
|
|
|
UuidCompare( &InterfaceIdVectors->IfId[i]->Uuid,
|
|
&ClientIf.InterfaceId.SyntaxGUID,
|
|
&Result );
|
|
|
|
if( Result == 0 ) {
|
|
|
|
*MajorVersion = InterfaceIdVectors->IfId[i]->VersMajor;
|
|
*MinorVersion = InterfaceIdVectors->IfId[i]->VersMinor;
|
|
Error = ERROR_SUCCESS;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Error = RPC_S_UNKNOWN_IF;
|
|
|
|
Cleanup:
|
|
|
|
if( InterfaceIdVectors != NULL ) {
|
|
RpcIfIdVectorFree( &InterfaceIdVectors );
|
|
}
|
|
|
|
if( BindingHandle != NULL ) {
|
|
DHCP_SRV_HANDLE_unbind( ServerIpAddress, BindingHandle );
|
|
}
|
|
|
|
return( Error );
|
|
}
|
|
#endif // 0
|
|
|
|
//
|
|
// NT4 SP1 interface
|
|
//
|
|
|
|
DWORD
|
|
DhcpAddSubnetElementV4(
|
|
DHCP_CONST WCHAR *ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V4 * AddElementInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpAddSubnetElementV4(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
AddElementInfo );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpAddSubnetElementV4DS(ServerIpAddress, SubnetAddress,AddElementInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
DhcpEnumSubnetElementsV4(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *EnumElementInfo,
|
|
DWORD *ElementsRead,
|
|
DWORD *ElementsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enumerates the eumerable fields of a subnet.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
EnumElementType : Type of the subnet element that are enumerated.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to
|
|
zero on first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
EnumElementInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up the buffer after use
|
|
by calling DhcpRPCFreeMemory().
|
|
|
|
ElementsRead : Pointer to a DWORD where the number of subnet
|
|
elements in the above buffer is returned.
|
|
|
|
ElementsTotal : Pointer to a DWORD where the total number of
|
|
elements remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpEnumSubnetElementsV4(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
EnumElementType,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
EnumElementInfo,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
|
|
return DhcpEnumSubnetElementsV4DS(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
EnumElementType,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
EnumElementInfo,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpRemoveSubnetElementV4(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
LPDHCP_SUBNET_ELEMENT_DATA_V4 RemoveElementInfo,
|
|
DHCP_FORCE_FLAG ForceFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a subnet element from managing. If the subnet
|
|
element is in use (for example, if the IpRange is in use) then it
|
|
returns error according to the ForceFlag specified.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
RemoveElementInfo : Pointer to an element information structure
|
|
containing element that should be removed from the subnet.
|
|
DhcpIPClusters element type is invalid to specify.
|
|
|
|
ForceFlag - Indicates how forcefully this element is removed.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains invalid
|
|
data.
|
|
|
|
DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
|
|
reason it is has been used.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpRemoveSubnetElementV4(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
RemoveElementInfo,
|
|
ForceFlag
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpRemoveSubnetElementV4DS(ServerIpAddress,SubnetAddress,RemoveElementInfo,ForceFlag);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpCreateClientInfoV4(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_CLIENT_INFO_V4 ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates a client record in server's database. Also
|
|
this marks the specified client IP address as unavailable (or
|
|
distributed). This function returns error under the following cases :
|
|
|
|
1. If the specified client IP address is not within the server
|
|
management.
|
|
|
|
2. If the specified client IP address is already unavailable.
|
|
|
|
3. If the specified client record is already in the server's
|
|
database.
|
|
|
|
This function may be used to distribute IP addresses manually.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ClientInfo : Pointer to the client information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_IP_ADDRESS_NOT_MANAGED - if the specified client
|
|
IP address is not managed by the server.
|
|
|
|
ERROR_DHCP_IP_ADDRESS_NOT_AVAILABLE - if the specified client IP
|
|
address is not available. May be in use by some other client.
|
|
|
|
ERROR_DHCP_CLIENT_EXISTS - if the client record exists already in
|
|
server's database.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpCreateClientInfoV4(
|
|
ServerIpAddress,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetClientInfoV4(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_SEARCH_INFO SearchInfo,
|
|
LPDHCP_CLIENT_INFO_V4 *ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves client information record from the server's
|
|
database.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SearchInfo : Pointer to a search information record which is the key
|
|
for the client's record search.
|
|
|
|
ClientInfo : Pointer to a location where the pointer to the client
|
|
information structure is returned. This caller should free up
|
|
this buffer after use by calling DhcpRPCFreeMemory().
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
|
|
not exist on the server's database.
|
|
|
|
ERROR_INVALID_PARAMETER - if the search information invalid.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetClientInfoV4(
|
|
ServerIpAddress,
|
|
SearchInfo,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetClientInfoV4DS(ServerIpAddress, SearchInfo, ClientInfo);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
DhcpSetClientInfoV4(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_CLIENT_INFO_V4 ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets client information record on the server's
|
|
database.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ClientInfo : Pointer to the client information structure.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
|
|
not exist on the server's database.
|
|
|
|
ERROR_INVALID_PARAMETER - if the client information structure
|
|
contains inconsistent data.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpSetClientInfoV4(
|
|
ServerIpAddress,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return Status;
|
|
|
|
return DhcpSetClientInfoV4DS(ServerIpAddress, ClientInfo);
|
|
}
|
|
|
|
DWORD
|
|
DhcpEnumSubnetClientsV4(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_CLIENT_INFO_ARRAY_V4 *ClientInfo,
|
|
DWORD *ClientsRead,
|
|
DWORD *ClientsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns all registered clients of the specified
|
|
subnet.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to zero on
|
|
first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
ClientInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up this buffer
|
|
after use by calling DhcpRPCFreeMemory().
|
|
|
|
ClientsRead : Pointer to a DWORD where the number of clients
|
|
that in the above buffer is returned.
|
|
|
|
ClientsTotal : Pointer to a DWORD where the total number of
|
|
clients remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumSubnetClientsV4(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
ClientInfo,
|
|
ClientsRead,
|
|
ClientsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpEnumSubnetClientsV5(
|
|
LPWSTR ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_CLIENT_INFO_ARRAY_V5 *ClientInfo,
|
|
DWORD *ClientsRead,
|
|
DWORD *ClientsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns all registered clients of the specified
|
|
subnet.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to zero on
|
|
first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
ClientInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up this buffer
|
|
after use by calling DhcpRPCFreeMemory().
|
|
|
|
ClientsRead : Pointer to a DWORD where the number of clients
|
|
that in the above buffer is returned.
|
|
|
|
ClientsTotal : Pointer to a DWORD where the total number of
|
|
clients remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumSubnetClientsV5(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
ClientInfo,
|
|
ClientsRead,
|
|
ClientsTotal
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpServerSetConfigV4(
|
|
LPWSTR ServerIpAddress,
|
|
DWORD FieldsToSet,
|
|
LPDHCP_SERVER_CONFIG_INFO_V4 ConfigInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets the DHCP server configuration information.
|
|
Serveral of the configuration information will become effective
|
|
immediately.
|
|
|
|
The following parameters require restart of the service after this
|
|
API is called successfully.
|
|
|
|
Set_APIProtocolSupport
|
|
Set_DatabaseName
|
|
Set_DatabasePath
|
|
Set_DatabaseLoggingFlag
|
|
Set_RestoreFlag
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
FieldsToSet : Bit mask of the fields in the ConfigInfo structure to
|
|
be set.
|
|
|
|
ConfigInfo: Pointer to the info structure to be set.
|
|
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpServerSetConfigV4(
|
|
ServerIpAddress,
|
|
FieldsToSet,
|
|
ConfigInfo );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpServerGetConfigV4(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_SERVER_CONFIG_INFO_V4 *ConfigInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the current configuration information of the
|
|
server.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ConfigInfo: Pointer to a location where the pointer to the dhcp
|
|
server config info structure is returned. Caller should free up
|
|
this structure after use.
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_CALL_NOT_IMPLEMENTED;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpServerGetConfigV4(
|
|
ServerIpAddress,
|
|
ConfigInfo );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
DhcpSetSuperScopeV4(
|
|
DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
|
|
DHCP_CONST DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_CONST LPWSTR SuperScopeName,
|
|
DHCP_CONST BOOL ChangeExisting
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept
|
|
{
|
|
Status = R_DhcpSetSuperScopeV4(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
SuperScopeName,
|
|
ChangeExisting
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
|
|
{
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetSuperScopeV4DS(ServerIpAddress,SubnetAddress,SuperScopeName,ChangeExisting);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpDeleteSuperScopeV4(
|
|
DHCP_CONST WCHAR *ServerIpAddress,
|
|
DHCP_CONST LPWSTR SuperScopeName
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept
|
|
{
|
|
Status = R_DhcpDeleteSuperScopeV4(
|
|
ServerIpAddress,
|
|
SuperScopeName
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
|
|
{
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpDeleteSuperScopeV4DS(ServerIpAddress,SuperScopeName);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetSuperScopeInfoV4(
|
|
DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
|
|
LPDHCP_SUPER_SCOPE_TABLE *SuperScopeTable
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpGetSuperScopeInfoV4(
|
|
ServerIpAddress,
|
|
SuperScopeTable
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
|
|
return DhcpGetSuperScopeInfoV4DS(ServerIpAddress, SuperScopeTable);
|
|
}
|
|
|
|
//================================================================================
|
|
// V5 NT 5.0 Beta2 work (ClassId and Vendor specific stuff)
|
|
// In the following function, if flags is DHCP_FLAGS_OPTION_IS_VENDOR
|
|
// implies the option being considered is vendor, otherwise the option is normal...
|
|
// ClasName = NULL imples there is no class (otherwise the class is named)
|
|
//================================================================================
|
|
|
|
DWORD // ERROR_DHCP_OPTION_EXITS if option is already there
|
|
DhcpCreateOptionV5( // create a new option (must not exist)
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN DHCP_OPTION_ID OptionId, // must be between 0-255 or 256-511 (for vendor stuff)
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN LPDHCP_OPTION OptionInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpCreateOptionV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionId,
|
|
ClassName,
|
|
VendorName,
|
|
OptionInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpCreateOptionV5DS(ServerIpAddress,Flags,OptionId,ClassName,VendorName,OptionInfo);
|
|
}
|
|
|
|
DWORD // ERROR_DHCP_OPTION_NOT_PRESENT if option does not exist
|
|
DhcpSetOptionInfoV5( // Modify existing option's fields
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN DHCP_OPTION_ID OptionID,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN LPDHCP_OPTION OptionInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpSetOptionInfoV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionID,
|
|
ClassName,
|
|
VendorName,
|
|
OptionInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetOptionInfoV5DS(ServerIpAddress,Flags,OptionID, ClassName, VendorName, OptionInfo);
|
|
}
|
|
|
|
|
|
DWORD // ERROR_DHCP_OPTION_NOT_PRESENT
|
|
DhcpGetOptionInfoV5( // retrieve the information from off the mem structures
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN DHCP_OPTION_ID OptionID,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
OUT LPDHCP_OPTION *OptionInfo // allocate memory using MIDL functions
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpGetOptionInfoV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionID,
|
|
ClassName,
|
|
VendorName,
|
|
OptionInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetOptionInfoV5DS(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionID,
|
|
ClassName,
|
|
VendorName,
|
|
OptionInfo
|
|
);
|
|
}
|
|
|
|
DWORD // ERROR_DHCP_OPTION_NOT_PRESENT if option does not exist
|
|
DhcpEnumOptionsV5( // enumerate the options defined
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN OUT DHCP_RESUME_HANDLE *ResumeHandle, // must be zero intially and then never touched
|
|
IN DWORD PreferredMaximum, // max # of bytes of info to pass along
|
|
OUT LPDHCP_OPTION_ARRAY *Options, // fill this option array
|
|
OUT DWORD *OptionsRead, // fill in the # of options read
|
|
OUT DWORD *OptionsTotal // fill in the total # here
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpEnumOptionsV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
ClassName,
|
|
VendorName,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
Options,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpEnumOptionsV5DS(
|
|
ServerIpAddress,
|
|
Flags,
|
|
ClassName,
|
|
VendorName,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
Options,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
}
|
|
|
|
DWORD // ERROR_DHCP_OPTION_NOT_PRESENT if option not existent
|
|
DhcpRemoveOptionV5( // remove the option definition from the registry
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN DHCP_OPTION_ID OptionID,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpRemoveOptionV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionID,
|
|
ClassName,
|
|
VendorName
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpRemoveOptionV5DS(ServerIpAddress, Flags,OptionID, ClassName, VendorName);
|
|
}
|
|
|
|
|
|
DWORD // OPTION_NOT_PRESENT if option is not defined
|
|
DhcpSetOptionValueV5( // replace or add a new option value
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN DHCP_OPTION_ID OptionId,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
IN LPDHCP_OPTION_DATA OptionValue
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpSetOptionValueV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionId,
|
|
ClassName,
|
|
VendorName,
|
|
ScopeInfo,
|
|
OptionValue
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetOptionValueV5DS(ServerIpAddress, Flags, OptionId, ClassName, VendorName, ScopeInfo, OptionValue);
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD // not atomic!!!!
|
|
DhcpSetOptionValuesV5( // set a bunch of options
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
IN LPDHCP_OPTION_VALUE_ARRAY OptionValues
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpSetOptionValuesV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
ClassName,
|
|
VendorName,
|
|
ScopeInfo,
|
|
OptionValues
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpSetOptionValuesV5DS(ServerIpAddress, Flags, ClassName, VendorName, ScopeInfo, OptionValues);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetOptionValueV5( // fetch the required option at required level
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN DHCP_OPTION_ID OptionID,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
OUT LPDHCP_OPTION_VALUE *OptionValue // allocate memory using MIDL_user_allocate
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpGetOptionValueV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionID,
|
|
ClassName,
|
|
VendorName,
|
|
ScopeInfo,
|
|
OptionValue
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetOptionValueV5DS(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionID,
|
|
ClassName,
|
|
VendorName,
|
|
ScopeInfo,
|
|
OptionValue
|
|
);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpEnumOptionValuesV5(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
IN DHCP_RESUME_HANDLE *ResumeHandle,
|
|
IN DWORD PreferredMaximum,
|
|
OUT LPDHCP_OPTION_VALUE_ARRAY *OptionValues,
|
|
OUT DWORD *OptionsRead,
|
|
OUT DWORD *OptionsTotal
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpEnumOptionValuesV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
ClassName,
|
|
VendorName,
|
|
ScopeInfo,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
OptionValues,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpEnumOptionValuesV5DS(
|
|
ServerIpAddress,
|
|
Flags,
|
|
ClassName,
|
|
VendorName,
|
|
ScopeInfo,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
OptionValues,
|
|
OptionsRead,
|
|
OptionsTotal
|
|
);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpRemoveOptionValueV5(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN DHCP_OPTION_ID OptionID,
|
|
IN LPWSTR ClassName,
|
|
IN LPWSTR VendorName,
|
|
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpRemoveOptionValueV5(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionID,
|
|
ClassName,
|
|
VendorName,
|
|
ScopeInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpRemoveOptionValueV5DS(ServerIpAddress,Flags,OptionID, ClassName, VendorName, ScopeInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpCreateClass(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD ReservedMustBeZero,
|
|
IN LPDHCP_CLASS_INFO ClassInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpCreateClass(
|
|
ServerIpAddress,
|
|
ReservedMustBeZero,
|
|
ClassInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpCreateClassDS(ServerIpAddress, ReservedMustBeZero, ClassInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpModifyClass(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD ReservedMustBeZero,
|
|
IN LPDHCP_CLASS_INFO ClassInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpModifyClass(
|
|
ServerIpAddress,
|
|
ReservedMustBeZero,
|
|
ClassInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpModifyClassDS(ServerIpAddress, ReservedMustBeZero, ClassInfo);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpDeleteClass(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD ReservedMustBeZero,
|
|
IN LPWSTR ClassName
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpDeleteClass(
|
|
ServerIpAddress,
|
|
ReservedMustBeZero,
|
|
ClassName
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
SkipRPC:
|
|
|
|
if( ERROR_SUCCESS != Status ) return Status;
|
|
if( DontAccessDs() ) return ERROR_SUCCESS; // dont do ds if asked not to.
|
|
|
|
return DhcpDeleteClassDS(ServerIpAddress,ReservedMustBeZero, ClassName);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpGetClassInfo(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD ReservedMustBeZero,
|
|
IN LPDHCP_CLASS_INFO PartialClassInfo,
|
|
OUT LPDHCP_CLASS_INFO *FilledClassInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpGetClassInfo(
|
|
ServerIpAddress,
|
|
ReservedMustBeZero,
|
|
PartialClassInfo,
|
|
FilledClassInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
return DhcpGetClassInfoDS(
|
|
ServerIpAddress,
|
|
ReservedMustBeZero,
|
|
PartialClassInfo,
|
|
FilledClassInfo
|
|
);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpEnumClasses(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD ReservedMustBeZero,
|
|
IN OUT DHCP_RESUME_HANDLE *ResumeHandle,
|
|
IN DWORD PreferredMaximum,
|
|
OUT LPDHCP_CLASS_INFO_ARRAY *ClassInfoArray,
|
|
OUT DWORD *nRead,
|
|
OUT DWORD *nTotal
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
*nRead = *nTotal =0;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpEnumClasses(
|
|
ServerIpAddress,
|
|
ReservedMustBeZero,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
ClassInfoArray,
|
|
nRead,
|
|
nTotal
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_SUCCESS;
|
|
|
|
return DhcpEnumClassesDS(
|
|
ServerIpAddress, ReservedMustBeZero, ResumeHandle, PreferredMaximum, ClassInfoArray, nRead, nTotal
|
|
);
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetAllOptions(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags, // what do we care about vendor/classid stuff?
|
|
OUT LPDHCP_ALL_OPTIONS *OptionStruct // fill the fields of this structure
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpGetAllOptions(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionStruct
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
if( DontAccessDs() ) return ERROR_INVALID_DATA;
|
|
|
|
return DhcpGetAllOptionsDS(
|
|
ServerIpAddress,
|
|
Flags,
|
|
OptionStruct
|
|
);
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetAllOptionValues(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags,
|
|
IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
|
|
OUT LPDHCP_ALL_OPTION_VALUES *Values
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if( DontDoRPC() ) goto SkipRPC;
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpGetAllOptionValues(
|
|
ServerIpAddress,
|
|
Flags,
|
|
ScopeInfo,
|
|
Values
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
return Status;
|
|
|
|
SkipRPC:
|
|
|
|
return DhcpGetAllOptionValuesDS(
|
|
ServerIpAddress,
|
|
Flags,
|
|
ScopeInfo,
|
|
Values
|
|
);
|
|
}
|
|
|
|
//DOC DhcpEnumServers enumerates the list of servers found in the DS. If the DS
|
|
//DOC is not accessible, it returns an error. The only currently used parameter
|
|
//DOC is the out parameter Servers. This is a SLOW call.
|
|
DWORD
|
|
DhcpEnumServers(
|
|
IN DWORD Flags, // must be zero
|
|
IN LPVOID IdInfo, // must be NULL
|
|
OUT LPDHCP_SERVER_INFO_ARRAY *Servers, // output servers list
|
|
IN LPVOID CallbackFn, // must be NULL
|
|
IN LPVOID CallbackData // must be NULL
|
|
)
|
|
{
|
|
DWORD Result;
|
|
|
|
Result = DhcpEnumServersDS(Flags,IdInfo,Servers,CallbackFn,CallbackData);
|
|
|
|
return Result;
|
|
}
|
|
|
|
//DOC DhcpAddServer tries to add a new server to the existing list of servers in
|
|
//DOC the DS. The function returns error if the Server already exists in the DS.
|
|
//DOC The function tries to upload the server configuration to the DS..
|
|
//DOC This is a SLOW call. Currently, the DsLocation and DsLocType are not valid
|
|
//DOC fields in the NewServer and they'd be ignored. Version must be zero.
|
|
DWORD
|
|
DhcpAddServer(
|
|
IN DWORD Flags, // must be zero
|
|
IN LPVOID IdInfo, // must be NULL
|
|
IN LPDHCP_SERVER_INFO NewServer, // input server information
|
|
IN LPVOID CallbackFn, // must be NULL
|
|
IN LPVOID CallbackData // must be NULL
|
|
)
|
|
{
|
|
DWORD Err, IpAddress;
|
|
WCHAR wBuf[sizeof("xxx.xxx.xxx.xxx")];
|
|
|
|
Err = DhcpAddServerDS(Flags,IdInfo,NewServer,CallbackFn,CallbackData);
|
|
if( ERROR_SUCCESS != Err ) return Err;
|
|
|
|
IpAddress = htonl(NewServer->ServerAddress);
|
|
(void)DhcpServerRedoAuthorization(
|
|
DhcpOemToUnicode( inet_ntoa(*(struct in_addr*)&IpAddress), wBuf),
|
|
0
|
|
);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//DOC DhcpDeleteServer tries to delete the server from DS. It is an error if the
|
|
//DOC server does not already exist. This also deletes any objects related to
|
|
//DOC this server in the DS (like subnet, reservations etc.).
|
|
DWORD
|
|
DhcpDeleteServer(
|
|
IN DWORD Flags, // must be zero
|
|
IN LPVOID IdInfo, // must be NULL
|
|
IN LPDHCP_SERVER_INFO NewServer, // input server information
|
|
IN LPVOID CallbackFn, // must be NULL
|
|
IN LPVOID CallbackData // must be NULL
|
|
)
|
|
{
|
|
DWORD Err, IpAddress;
|
|
WCHAR wBuf[sizeof("xxx.xxx.xxx.xxx")];
|
|
|
|
Err = DhcpDeleteServerDS(Flags,IdInfo,NewServer,CallbackFn,CallbackData);
|
|
if( ERROR_SUCCESS != Err ) return Err;
|
|
|
|
IpAddress = htonl(NewServer->ServerAddress);
|
|
(void)DhcpServerRedoAuthorization(
|
|
DhcpOemToUnicode( inet_ntoa(*(struct in_addr*)&IpAddress), wBuf),
|
|
0
|
|
);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//================================================================================
|
|
// Multicast stuff
|
|
//================================================================================
|
|
|
|
DWORD
|
|
DhcpSetMScopeInfo(
|
|
DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
LPDHCP_MSCOPE_INFO MScopeInfo,
|
|
BOOL NewScope
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept
|
|
{
|
|
Status = R_DhcpSetMScopeInfo(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
MScopeInfo,
|
|
NewScope
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
|
|
{
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetMScopeInfo(
|
|
DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
LPDHCP_MSCOPE_INFO *MScopeInfo
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept
|
|
{
|
|
Status = R_DhcpGetMScopeInfo(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
MScopeInfo
|
|
);
|
|
}
|
|
RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
|
|
{
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpEnumMScopes(
|
|
DHCP_CONST WCHAR *ServerIpAddress,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_MSCOPE_TABLE *MScopeTable,
|
|
DWORD *ElementsRead,
|
|
DWORD *ElementsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enumerates the available subnets.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to
|
|
zero on first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
ElementsRead : Pointer to a DWORD where the number of subnet
|
|
elements in the above buffer is returned.
|
|
|
|
ElementsTotal : Pointer to a DWORD where the total number of
|
|
elements remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumMScopes(
|
|
ServerIpAddress,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
MScopeTable,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpAddMScopeElement(
|
|
LPWSTR ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
LPDHCP_SUBNET_ELEMENT_DATA_V4 AddElementInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function adds a enumerable type of subnet elements to the
|
|
specified subnet. The new elements that are added to the subnet will
|
|
come into effect immediately.
|
|
|
|
NOTE: It is not clear now how do we handle the new secondary hosts.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
AddElementInfo : Pointer to an element information structure
|
|
containing new element that is added to the subnet.
|
|
DhcpIPClusters element type is invalid to specify.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains invalid
|
|
data.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpAddMScopeElement(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
AddElementInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpEnumMScopeElements(
|
|
LPWSTR ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *EnumElementInfo,
|
|
DWORD *ElementsRead,
|
|
DWORD *ElementsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enumerates the eumerable fields of a subnet.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
EnumElementType : Type of the subnet element that are enumerated.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to
|
|
zero on first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
EnumElementInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up the buffer after use
|
|
by calling DhcpRPCFreeMemory().
|
|
|
|
ElementsRead : Pointer to a DWORD where the number of subnet
|
|
elements in the above buffer is returned.
|
|
|
|
ElementsTotal : Pointer to a DWORD where the total number of
|
|
elements remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumMScopeElements(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
EnumElementType,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
EnumElementInfo,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpRemoveMScopeElement(
|
|
LPWSTR ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
LPDHCP_SUBNET_ELEMENT_DATA_V4 RemoveElementInfo,
|
|
DHCP_FORCE_FLAG ForceFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a subnet element from managing. If the subnet
|
|
element is in use (for example, if the IpRange is in use) then it
|
|
returns error according to the ForceFlag specified.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
RemoveElementInfo : Pointer to an element information structure
|
|
containing element that should be removed from the subnet.
|
|
DhcpIPClusters element type is invalid to specify.
|
|
|
|
ForceFlag - Indicates how forcefully this element is removed.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains invalid
|
|
data.
|
|
|
|
DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
|
|
reason it is has been used.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpRemoveMScopeElement(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
RemoveElementInfo,
|
|
ForceFlag
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpDeleteMScope(
|
|
LPWSTR ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
DHCP_FORCE_FLAG ForceFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a subnet from DHCP server management. If the
|
|
subnet is in use (for example, if the IpRange is in use)
|
|
then it returns error according to the ForceFlag specified.
|
|
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
ForceFlag - Indicates how forcefully this element is removed.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_INVALID_PARAMETER - if the information structure contains invalid
|
|
data.
|
|
|
|
DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
|
|
reason it is has been used.
|
|
|
|
Other WINDOWS errors.
|
|
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpDeleteMScope(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
ForceFlag
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetMClientInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_SEARCH_INFO SearchInfo,
|
|
LPDHCP_MCLIENT_INFO *ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves client information record from the server's
|
|
database.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SearchInfo : Pointer to a search information record which is the key
|
|
for the client's record search.
|
|
|
|
ClientInfo : Pointer to a location where the pointer to the client
|
|
information structure is returned. This caller should free up
|
|
this buffer after use by calling DhcpRPCFreeMemory().
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
|
|
not exist on the server's database.
|
|
|
|
ERROR_INVALID_PARAMETER - if the search information invalid.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetMClientInfo(
|
|
ServerIpAddress,
|
|
SearchInfo,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpDeleteMClientInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_SEARCH_INFO ClientInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function deletes the specified client record. Also it frees up
|
|
the client IP address for redistribution.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
ClientInfo : Pointer to a client information which is the key for
|
|
the client's record search.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
|
|
not exist on the server's database.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpDeleteMClientInfo(
|
|
ServerIpAddress,
|
|
ClientInfo
|
|
);
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpEnumMScopeClients(
|
|
LPWSTR ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_MCLIENT_INFO_ARRAY *ClientInfo,
|
|
DWORD *ClientsRead,
|
|
DWORD *ClientsTotal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns all registered clients of the specified
|
|
subnet.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : IP Address of the subnet.
|
|
|
|
ResumeHandle : Pointer to a resume handle where the resume
|
|
information is returned. The resume handle should be set to zero on
|
|
first call and left unchanged for subsequent calls.
|
|
|
|
PreferredMaximum : Preferred maximum length of the return buffer.
|
|
|
|
ClientInfo : Pointer to a location where the return buffer
|
|
pointer is stored. Caller should free up this buffer
|
|
after use by calling DhcpRPCFreeMemory().
|
|
|
|
ClientsRead : Pointer to a DWORD where the number of clients
|
|
that in the above buffer is returned.
|
|
|
|
ClientsTotal : Pointer to a DWORD where the total number of
|
|
clients remaining from the current position is returned.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
|
|
|
|
ERROR_MORE_DATA - if more elements available to enumerate.
|
|
|
|
ERROR_NO_MORE_ITEMS - if no more element to enumerate.
|
|
|
|
Other WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpEnumMScopeClients(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
ClientInfo,
|
|
ClientsRead,
|
|
ClientsTotal
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
DWORD
|
|
DhcpScanMDatabase(
|
|
LPWSTR ServerIpAddress,
|
|
LPWSTR MScopeName,
|
|
DWORD FixFlag,
|
|
LPDHCP_SCAN_LIST *ScanList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function scans the database entries and registry bit-map for
|
|
specified subnet scope and veryfies to see they match. If they
|
|
don't match, this api will return the list of inconsistent entries.
|
|
Optionally FixFlag can be used to fix the bad entries.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
SubnetAddress : Address of the subnet scope to verify.
|
|
|
|
FixFlag : If this flag is TRUE, this api will fix the bad entries.
|
|
|
|
ScanList : List of bad entries returned. The caller should free up
|
|
this memory after it has been used.
|
|
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpScanMDatabase(
|
|
ServerIpAddress,
|
|
MScopeName,
|
|
FixFlag,
|
|
ScanList );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpGetMCastMibInfo(
|
|
LPWSTR ServerIpAddress,
|
|
LPDHCP_MCAST_MIB_INFO *MibInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves all counter values of the DHCP server
|
|
service.
|
|
|
|
Arguments:
|
|
|
|
ServerIpAddress : IP address string of the DHCP server.
|
|
|
|
MibInfo : pointer a counter/table buffer. Caller should free up this
|
|
buffer after usage.
|
|
|
|
Return Value:
|
|
|
|
WINDOWS errors.
|
|
--*/
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
|
|
Status = R_DhcpGetMCastMibInfo(
|
|
ServerIpAddress,
|
|
MibInfo );
|
|
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
|
|
Status = RpcExceptionCode();
|
|
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpAuditLogSetParams( // set some auditlogging params
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags, // currently must be zero
|
|
IN LPWSTR AuditLogDir, // directory to log files in..
|
|
IN DWORD DiskCheckInterval, // how often to check disk space?
|
|
IN DWORD MaxLogFilesSize, // how big can all logs files be..
|
|
IN DWORD MinSpaceOnDisk // mininum amt of free disk space
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpAuditLogSetParams(
|
|
ServerIpAddress,
|
|
Flags,
|
|
AuditLogDir,
|
|
DiskCheckInterval,
|
|
MaxLogFilesSize,
|
|
MinSpaceOnDisk
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpAuditLogGetParams( // get the auditlogging params
|
|
IN LPWSTR ServerIpAddress,
|
|
IN DWORD Flags, // must be zero
|
|
OUT LPWSTR *AuditLogDir, // same meaning as in AuditLogSetParams
|
|
OUT DWORD *DiskCheckInterval, // ditto
|
|
OUT DWORD *MaxLogFilesSize, // ditto
|
|
OUT DWORD *MinSpaceOnDisk // ditto
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpAuditLogGetParams(
|
|
ServerIpAddress,
|
|
Flags,
|
|
AuditLogDir,
|
|
DiskCheckInterval,
|
|
MaxLogFilesSize,
|
|
MinSpaceOnDisk
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD // Status code
|
|
DhcpServerQueryAttribute( // get a server status
|
|
IN LPWSTR ServerIpAddr, // String form of server IP
|
|
IN ULONG dwReserved, // reserved for future
|
|
IN DHCP_ATTRIB_ID DhcpAttribId, // the attrib being queried
|
|
OUT LPDHCP_ATTRIB *pDhcpAttrib // fill in this field
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpServerQueryAttribute(
|
|
ServerIpAddr,
|
|
dwReserved,
|
|
DhcpAttribId,
|
|
pDhcpAttrib
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD // Status code
|
|
DhcpServerQueryAttributes( // query multiple attributes
|
|
IN LPWSTR ServerIpAddr, // String form of server IP
|
|
IN ULONG dwReserved, // reserved for future
|
|
IN ULONG dwAttribCount, // # of attribs being queried
|
|
IN DHCP_ATTRIB_ID pDhcpAttribs[],// array of attribs
|
|
OUT LPDHCP_ATTRIB_ARRAY *pDhcpAttribArr // Ptr is filled w/ array
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpServerQueryAttributes(
|
|
ServerIpAddr,
|
|
dwReserved,
|
|
dwAttribCount,
|
|
pDhcpAttribs,
|
|
pDhcpAttribArr
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD // Status code
|
|
DhcpServerRedoAuthorization( // retry the rogue server stuff
|
|
IN LPWSTR ServerIpAddr, // String form of server IP
|
|
IN ULONG dwReserved // reserved for future
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpServerRedoAuthorization(
|
|
ServerIpAddr,
|
|
dwReserved
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD DHCP_API_FUNCTION
|
|
DhcpAddSubnetElementV5(
|
|
DHCP_CONST WCHAR *ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V5 * AddElementInfo
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpAddSubnetElementV5(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
AddElementInfo
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD DHCP_API_FUNCTION
|
|
DhcpEnumSubnetElementsV5(
|
|
DHCP_CONST WCHAR *ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
|
|
DHCP_RESUME_HANDLE *ResumeHandle,
|
|
DWORD PreferredMaximum,
|
|
LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5 *EnumElementInfo,
|
|
DWORD *ElementsRead,
|
|
DWORD *ElementsTotal
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpEnumSubnetElementsV5(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
EnumElementType,
|
|
ResumeHandle,
|
|
PreferredMaximum,
|
|
EnumElementInfo,
|
|
ElementsRead,
|
|
ElementsTotal
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD DHCP_API_FUNCTION
|
|
DhcpRemoveSubnetElementV5(
|
|
DHCP_CONST WCHAR *ServerIpAddress,
|
|
DHCP_IP_ADDRESS SubnetAddress,
|
|
DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V5 * RemoveElementInfo,
|
|
DHCP_FORCE_FLAG ForceFlag
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpRemoveSubnetElementV5(
|
|
ServerIpAddress,
|
|
SubnetAddress,
|
|
RemoveElementInfo,
|
|
ForceFlag
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD DHCP_API_FUNCTION
|
|
DhcpSetServerBindingInfo(
|
|
IN DHCP_CONST WCHAR *ServerIpAddress,
|
|
IN ULONG Flags,
|
|
IN LPDHCP_BIND_ELEMENT_ARRAY BindInfo
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpSetServerBindingInfo(
|
|
ServerIpAddress,
|
|
Flags,
|
|
BindInfo
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD DHCP_API_FUNCTION
|
|
DhcpGetServerBindingInfo(
|
|
IN DHCP_CONST WCHAR *ServerIpAddress,
|
|
IN ULONG Flags,
|
|
OUT LPDHCP_BIND_ELEMENT_ARRAY *BindInfo
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpGetServerBindingInfo(
|
|
ServerIpAddress,
|
|
Flags,
|
|
BindInfo
|
|
);
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DhcpServerQueryDnsRegCredentials(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN ULONG UnameSize, //in BYTES
|
|
OUT LPWSTR Uname,
|
|
IN ULONG DomainSize, // in BYTES
|
|
OUT LPWSTR Domain
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpQueryDnsRegCredentials(
|
|
ServerIpAddress,
|
|
UnameSize/sizeof(WCHAR), Uname,
|
|
DomainSize/sizeof(WCHAR), Domain );
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpServerSetDnsRegCredentials(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN LPWSTR Uname,
|
|
IN LPWSTR Domain,
|
|
IN LPWSTR Passwd
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpSetDnsRegCredentials(
|
|
ServerIpAddress, Uname, Domain, Passwd );
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpServerBackupDatabase(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN LPWSTR Path
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpBackupDatabase(
|
|
ServerIpAddress, Path );
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DhcpServerRestoreDatabase(
|
|
IN LPWSTR ServerIpAddress,
|
|
IN LPWSTR Path
|
|
)
|
|
{
|
|
ULONG Status;
|
|
|
|
RedoRpc: RpcTryExcept {
|
|
Status = R_DhcpRestoreDatabase(
|
|
ServerIpAddress, Path );
|
|
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
|
|
Status = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
|
|
!DhcpGlobalTryDownlevel ) {
|
|
DhcpGlobalTryDownlevel = TRUE;
|
|
goto RedoRpc;
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
#define BINL_SVC_NAME L"binlsvc"
|
|
|
|
BOOL
|
|
BinlServiceInstalled(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks if BINL service has been installed.
|
|
BINL service is "binlsvc"
|
|
|
|
Return Values;
|
|
|
|
TRUE -- binl service is installed
|
|
FALSE -- binl service is not installed
|
|
|
|
--*/
|
|
{
|
|
SC_HANDLE hScManager, hService;
|
|
ULONG Error, Attempt;
|
|
SERVICE_STATUS ServiceStatus;
|
|
|
|
hScManager = OpenSCManager(
|
|
NULL, NULL,
|
|
STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE
|
|
);
|
|
if( NULL == hScManager ) {
|
|
DbgPrint("DHCP: OpenSCManager failed 0x%lx\n", GetLastError());
|
|
//ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
hService = OpenService(
|
|
hScManager, BINL_SVC_NAME,
|
|
SERVICE_QUERY_STATUS
|
|
);
|
|
|
|
#if DBG
|
|
if( NULL == hService ) {
|
|
ULONG Error;
|
|
|
|
Error = GetLastError();
|
|
if( ERROR_SERVICE_DOES_NOT_EXIST != Error ) {
|
|
//ASSERT(FALSE);
|
|
}
|
|
DbgPrint("DHCP: Can't open BINLSVC service: 0x%lx\n", Error);
|
|
}
|
|
#endif
|
|
|
|
CloseServiceHandle(hService);
|
|
CloseServiceHandle(hScManager);
|
|
|
|
return (NULL != hService);
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
DhcpDsClearHostServerEntries(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine clears off any entries in DS for the current host assuming
|
|
it has permissions to do so..
|
|
|
|
--*/
|
|
{
|
|
ULONG Error;
|
|
struct hostent *HostEnt;
|
|
int i, j;
|
|
WSADATA wsadata;
|
|
LPDHCP_SERVER_INFO_ARRAY Servers = NULL;
|
|
|
|
if( BinlServiceInstalled() ) {
|
|
//
|
|
// Do not do anything if BINL is installed
|
|
//
|
|
return ;
|
|
}
|
|
|
|
Error = WSAStartup( 0x0101, &wsadata);
|
|
if( ERROR_SUCCESS != Error ) {
|
|
return;
|
|
}
|
|
|
|
do {
|
|
HostEnt = gethostbyname( NULL );
|
|
if( NULL == HostEnt ) break;
|
|
|
|
//
|
|
// Now try to start the DS module..
|
|
//
|
|
Error = DhcpDsInit();
|
|
if( ERROR_SUCCESS != Error ) break;
|
|
|
|
do {
|
|
Error = DhcpEnumServers(
|
|
0,
|
|
NULL,
|
|
&Servers,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if( ERROR_SUCCESS != Error ) break;
|
|
|
|
i = 0;
|
|
if( !Servers ) break;
|
|
|
|
while( HostEnt->h_addr_list[i] ) {
|
|
ULONG Addr = *(ULONG *)(HostEnt->h_addr_list[i]);
|
|
|
|
i ++;
|
|
if( Addr == 0 || Addr == ~0 || Addr == INADDR_LOOPBACK )
|
|
continue;
|
|
|
|
for( j = 0; j < (int)Servers->NumElements; j ++ ) {
|
|
if( Addr == ntohl(Servers->Servers[j].ServerAddress )) {
|
|
DhcpDeleteServer(
|
|
0,
|
|
NULL,
|
|
&Servers->Servers[j],
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
DhcpRpcFreeMemory( Servers );
|
|
} while ( 0 );
|
|
|
|
DhcpDsCleanup();
|
|
} while ( 0 );
|
|
|
|
WSACleanup();
|
|
}
|
|
|
|
//================================================================================
|
|
// end of file
|
|
//================================================================================
|