windows-nt/Source/XPSP1/NT/net/dhcp/client/nt/apiappl.c

2244 lines
80 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "precomp.h"
#ifdef H_ONLY
//================================================================================
// Copyright (C) 1997 Microsoft Corporation
// Author: RameshV
// Description: these are the exported dhcp client api function definitions
//================================================================================
#ifndef APIAPPL_H_INCLUDED
#define APIAPPL_H_INCLUDED
#ifndef DHCPAPI_PARAMS_DEFINED
#define DHCPAPI_PARAMS_DEFINED
typedef struct _DHCPAPI_PARAMS { // use this structure to request params
ULONG Flags; // for future use
ULONG OptionId; // what option is this?
BOOL IsVendor; // is this vendor specific?
LPBYTE Data; // the actual data
DWORD nBytesData; // how many bytes of data are there in Data?
} DHCPAPI_PARAMS, *PDHCPAPI_PARAMS, *LPDHCPAPI_PARAMS;
#endif DHCPAPI_PARAMS_DEFINED
DWORD // win32 status
DhcpAcquireParameters( // acquire/renew a lease
IN LPWSTR AdapterName // adapter to acquire lease on
);
DWORD // win32 status
DhcpAcquireParametersByBroadcast( // acquire/renew a lease
IN LPWSTR AdapterName // adapter to acquire lease on
);
DWORD // win32 status
DhcpFallbackRefreshParams( // refresh fallback params
IN LPWSTR AdapterName // adapter to be refreshed
);
DWORD // win32 status
DhcpReleaseParameters( // release an existing lease
IN LPWSTR AdapterName // adpater to release lease for
);
DWORD // win32 status
DhcpEnableDynamicConfic( // convert from static to dhcp
IN LPWSTR AdapterName // convert for this adapter
);
DWORD // win32 status
DhcpDisableDynamicConfig( // convert from dhcp to static
IN LPWSTR AdapterName // convert this adapter
);
DWORD // win32 status
DhcpReRegisterDynDns( // reregister static address with dns
IN LPWSTR AdapterName
);
DWORD // win32 status
APIENTRY
DhcpRequestParams( // request parameters of client
IN LPWSTR AdapterName, // adapter name to request for
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id to use
IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
IN DWORD nSendParams, // size of above array
IN DWORD Flags, // must be zero, reserved
IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
IN OUT LPDWORD pnRecdParamsBytes // i/p: size of above in BYTES, o/p required bytes or filled up # of elements
); // returns ERROR_MORE_DATA if o/p buffer is of insufficient size, and fills in reqd size in # of bytes
DWORD // win32 status
DhcpRegisterParameterChangeNotification( // notify if a parameter has changed
IN LPWSTR AdapterName, // adapter of interest
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id
IN PDHCPAPI_PARAMS Params, // params of interest
IN DWORD nParams, // # of elts in above array
IN DWORD Flags, // must be zero, reserved
IN OUT PHANDLE hEvent // handle to event that will be SetEvent'ed in case of param change
);
DhcpDeRegisterParameterChangeNotification( // undo the registration
IN HANDLE Event // handle to event returned by DhcpRegisterParameterChangeNotification, NULL ==> everything
);
DWORD // win32 status
DhcpPersistentRequestParams( // parameters to request persistently
IN LPWSTR AdapterName, // adapter name to request for
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id
IN PDHCPAPI_PARAMS SendParams, // persistent parameters
IN DWORD nSendParams, // size of above array
IN DWORD Flags, // must be zero, reserved
IN LPWSTR AppName, // the name of the app that is to be used for this instance
IN OUT LPDWORD UniqueId // OPTIONAL, return value is id that can be used in DhcpDelPersistentRequestParams
);
DWORD // win32 status
DhcpDelPersistentRequestParams( // undo the effect of a persistent request -- currently undo from registry
IN LPWSTR AdapterName, // the name of the adpater to delete for
IN LPWSTR AppName, // the name used by the app
IN DWORD UniqueId // something for this instance
);
#endif APIAPPL_H_INCLUDED
#else H_ONLY
#include <apiargs.h>
#include <apistub.h>
#include <apiimpl.h>
#include <apiappl.h>
#include <dhcploc.h>
#include <dhcppro.h>
#include <dhcpcsdk.h>
DWORD INLINE // win32 status
DhcpApiFillBuffer( // fill the buffer with some params
IN OUT LPBYTE Buffer, // the buffer to fill
IN DWORD MaxBufferSize, // the max size of buffer allwoed
IN LPWSTR AdapterName, // fill in adapter name
IN BYTE OpCode // what opcode to use?
) {
DWORD Size;
if( NULL == AdapterName ) Size = 0;
else Size = (wcslen(AdapterName)+1)*sizeof(WCHAR);
return DhcpApiArgAdd( // fill in the buffer with the reqd options
Buffer,
MaxBufferSize,
OpCode,
Size,
(LPBYTE)AdapterName
);
}
DWORD INLINE // win32 status
DhcpAdapterOnlyApi( // execute apis that take only adapter name params
IN LPWSTR AdapterName, // the adapter name
IN BYTE OpCode
)
{
LPBYTE Buffer;
LPBYTE Buffer2;
DWORD BufSize;
DWORD Size;
DWORD Error;
BufSize = 0;
Error = DhcpApiFillBuffer((LPBYTE)&BufSize, sizeof(BufSize), AdapterName, OpCode);
DhcpAssert( ERROR_SUCCESS != Error );
if( ERROR_MORE_DATA != Error ) return Error;
DhcpAssert(BufSize);
BufSize = ntohl(BufSize) + 2*sizeof(DWORD);
Buffer = DhcpAllocateMemory(BufSize);
if( NULL == Buffer ) return ERROR_NOT_ENOUGH_MEMORY;
*(DWORD UNALIGNED *)Buffer = htonl(0);
Buffer2 = Buffer + sizeof(DWORD);
*(DWORD UNALIGNED *)Buffer2 = 0;
BufSize -= sizeof(DWORD);
Error = DhcpApiFillBuffer(Buffer2, BufSize, AdapterName, OpCode);
Size = 0;
if( ERROR_SUCCESS == Error ) Error = ExecuteApiRequest(Buffer, NULL, &Size);
DhcpFreeMemory(Buffer);
return Error;
}
DWORD // win32 status
DhcpAcquireParameters( // acquire/renew a lease
IN LPWSTR AdapterName // adapter to acquire lease on
) {
return DhcpAdapterOnlyApi(AdapterName, AcquireParametersOpCode);
}
DWORD // win32 status
DhcpAcquireParametersByBroadcast( // acquire/renew a lease
IN LPWSTR AdapterName // adapter to acquire lease on
) {
return DhcpAdapterOnlyApi(AdapterName, AcquireParametersByBroadcastOpCode);
}
DWORD // win32 status
DhcpFallbackRefreshParams( // refresh fallback params
IN LPWSTR AdapterName // adapter to be refreshed
)
{
return DhcpAdapterOnlyApi(AdapterName, FallbackParamsOpCode);
}
DWORD // win32 status
DhcpReleaseParameters( // release an existing lease
IN LPWSTR AdapterName // adpater to release lease for
) {
return DhcpAdapterOnlyApi(AdapterName, ReleaseParametersOpCode);
}
DWORD // win32 status
DhcpEnableDynamicConfig( // convert from static to dhcp
IN LPWSTR AdapterName // convert for this adapter
) {
return DhcpAdapterOnlyApi(AdapterName, EnableDhcpOpCode);
}
DWORD // win32 status
DhcpDisableDynamicConfig( // convert from dhcp to static
IN LPWSTR AdapterName // convert this adapter
) {
return DhcpAdapterOnlyApi(AdapterName, DisableDhcpOpCode);
}
DWORD // win32 status
DhcpStaticRefreshParamsInternal( // refresh some static parameters that have changed
IN LPWSTR AdapterName,
IN BOOL fDoDns
)
{
LPBYTE Buffer, Buffer2;
DWORD BufSize, Size, Error, Code;
BufSize = 0;
Error = DhcpApiFillBuffer(
(LPBYTE)&BufSize, sizeof(BufSize), AdapterName, StaticRefreshParamsOpCode
);
if( ERROR_MORE_DATA != Error ) return Error;
DhcpAssert( BufSize );
BufSize = ntohl(BufSize) + 2 * sizeof(DWORD);
BufSize += 3*sizeof(DWORD);
Buffer = DhcpAllocateMemory( BufSize );
if( NULL == Buffer ) return ERROR_NOT_ENOUGH_MEMORY;
*(DWORD*)Buffer = 0;
Buffer2 = Buffer + sizeof(DWORD);
*(DWORD*)Buffer2 = 0;
BufSize -= sizeof(DWORD);
Error = DhcpApiFillBuffer(
Buffer2, BufSize, AdapterName, StaticRefreshParamsOpCode
);
DhcpAssert( ERROR_SUCCESS == Error );
Code = (fDoDns ? 0x00 : 0x01);
Error = DhcpApiArgAdd(
Buffer2, BufSize, (BYTE)FlagsParam, sizeof(DWORD), (LPBYTE)&Code
);
DhcpAssert( ERROR_SUCCESS == Error );
Size = 0;
Error = ExecuteApiRequest(Buffer, NULL, &Size);
DhcpFreeMemory( Buffer );
return Error;
}
DWORD
DhcpStaticRefreshParams(
IN LPWSTR AdapterName
)
{
return DhcpStaticRefreshParamsInternal(AdapterName, TRUE );
}
#if 0
// pl dont use this api, use DhcpRequestParams instead.
DWORD // win32 status
DhcpRequestOptions( // request for specific options
IN LPWSTR AdapterName, // which adapter's info is needed
IN LPBYTE RequestedOpt, // list of requested options
IN DWORD nRequestedOpts,// size of above BYTE array
OUT LPBYTE *OptData, // the data for each available option
IN OUT LPDWORD OptDataSize, // # of bytes of above byte array
OUT LPBYTE *AvailOpts, // the list of available options
IN OUT LPDWORD nAvailOpts // # of available options
) {
PDHCP_API_ARGS DhcpApiArgs;
CHAR TmpBuf[OPTION_END+1];
LPBYTE OutBuf;
LPBYTE InBuf;
LPBYTE Buffer;
LPBYTE Endp;
LPBYTE RetOptList;
LPBYTE RetDataList;
DWORD Size;
DWORD OutBufSize;
DWORD InBufSize;
DWORD i;
DWORD nArgsReturned;
DWORD Error;
BOOL Tmp;
// check parameter consistency
if( NULL == AdapterName || NULL == RequestedOpt || 0 == nRequestedOpts )
return ERROR_INVALID_PARAMETER;
if( NULL == AvailOpts || 0 == nAvailOpts || NULL == OptData || 0 == OptDataSize )
return ERROR_INVALID_PARAMETER;
if( nRequestedOpts >= OPTION_END ) return ERROR_NO_SYSTEM_RESOURCES;
// initialize out params
(*nAvailOpts) = (*OptDataSize) = 0;
(*AvailOpts) = (*OptData) = NULL;
// calculate input buffer size for ONE option to be sent and allocate it
InBufSize = 0;
InBufSize += sizeof(DWORD)*2; // INBUF_SIZE, OUTBUF_SIZE
InBufSize += sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR);
InBufSize += sizeof(BYTE)+sizeof(DWORD)+nRequestedOpts+sizeof(BYTE);
InBuf = DhcpAllocateMemory(InBufSize);
if( NULL == InBuf ) return ERROR_NOT_ENOUGH_MEMORY;
// intialize ptrs
OutBufSize = 0; OutBuf = NULL;
DhcpApiArgs = NULL;
RetOptList = RetDataList = NULL;
// now fill the input buffer
((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
((DWORD UNALIGNED*)InBuf)[1] = 0;
Buffer = InBuf + sizeof(DWORD); InBufSize -= sizeof(DWORD);
Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, RequestParamsOpCode);
DhcpAssert(ERROR_SUCCESS == Error);
TmpBuf[0] = (BYTE)OPTION_PARAMETER_REQUEST_LIST;
memcpy(&TmpBuf[1], RequestedOpt, nRequestedOpts);
Error = DhcpApiArgAdd(Buffer, InBufSize, NormalOptionParam, nRequestedOpts+1, TmpBuf);
DhcpAssert(ERROR_SUCCESS == Error);
Error = ExecuteApiRequest(InBuf, NULL, &OutBufSize);
if( ERROR_SUCCESS == Error ) {
DhcpAssert(0 == OutBufSize);
goto Cleanup;
}
if( ERROR_MORE_DATA != Error ) goto Cleanup; // ERROR_MORE_DATA ==> need to allocate buffer
DhcpPrint((DEBUG_OPTIONS, "RequestOptions: retrying with buffer size [%ld]\n", OutBufSize));
DhcpAssert(OutBufSize);
OutBuf = DhcpAllocateMemory(OutBufSize);
if( NULL == OutBuf) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
Error = ExecuteApiRequest(InBuf, OutBuf, &OutBufSize);
DhcpAssert(ERROR_MORE_DATA != Error); // can happen, just hope it does not...
if( ERROR_SUCCESS != Error ) goto Cleanup; // unexpected error
nArgsReturned = 0;
DhcpApiArgs = NULL;
Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned );
if( ERROR_MORE_DATA != Error ) goto Cleanup;
DhcpAssert(nArgsReturned);
if( 0 == nArgsReturned ) goto Cleanup; // no options sent? funny.. still, quit its
DhcpApiArgs = DhcpAllocateMemory(sizeof(DHCP_API_ARGS)*nArgsReturned);
if( NULL == DhcpApiArgs ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
nArgsReturned = 0;
Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
if( ERROR_SUCCESS != Error ) {
DhcpAssert(FALSE);
goto Cleanup;
}
DhcpAssert(nArgsReturned);
RetOptList = DhcpAllocateMemory(nArgsReturned);
if( NULL == RetOptList ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
Size = 0;
for( i = 0; i < nArgsReturned; i ++ ) {
DhcpAssert(DhcpApiArgs[i].ArgId == NormalOptionParam);
if( DhcpApiArgs[i].ArgId != NormalOptionParam ) continue;
DhcpAssert(DhcpApiArgs[i].ArgSize <= OPTION_END +1 );
if( DhcpApiArgs[i].ArgSize <= 1 ) continue;
Size += DhcpApiArgs[i].ArgSize;
}
RetDataList = DhcpAllocateMemory(Size);
if( NULL == RetDataList ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
Size = 0;
for(i = 0; i < nArgsReturned; i ++ ) {
if( DhcpApiArgs[i].ArgId != NormalOptionParam ) continue;
if( DhcpApiArgs[i].ArgSize <= 1 ) continue;
RetOptList[i] = DhcpApiArgs[i].ArgVal[0];
RetDataList[Size++] = (BYTE)(DhcpApiArgs[i].ArgSize - 1);
memcpy(&RetDataList[Size], DhcpApiArgs[i].ArgVal, DhcpApiArgs[i].ArgSize - 1);
Size += DhcpApiArgs[i].ArgSize - 1;
}
(*AvailOpts) = RetOptList;
(*nAvailOpts) = nArgsReturned;
(*OptData) = RetDataList;
(*OptDataSize) = Size;
DhcpFreeMemory(InBuf);
DhcpFreeMemory(OutBuf);
DhcpFreeMemory(DhcpApiArgs);
return ERROR_SUCCESS;
Cleanup:
if( InBuf ) DhcpFreeMemory(InBuf);
if( OutBuf ) DhcpFreeMemory(OutBuf);
if( DhcpApiArgs ) DhcpFreeMemory(DhcpApiArgs);
if( RetDataList ) DhcpFreeMemory(RetDataList);
if( RetOptList) DhcpFreeMemory(RetOptList);
return Error;
}
#endif
// pl dont use this api, use DhcpRequestParams instead.
DWORD // win32 status
DhcpRequestOptions( // request for specific options
IN LPWSTR AdapterName, // which adapter's info is needed
IN LPBYTE RequestedOpt, // list of requested options
IN DWORD nRequestedOpts,// size of above BYTE array
OUT LPBYTE *OptData, // the data for each available option
IN OUT LPDWORD OptDataSize, // # of bytes of above byte array
OUT LPBYTE *AvailOpts, // the list of available options
IN OUT LPDWORD nAvailOpts // # of available options
) {
DHCPAPI_PARAMS SendParams;
PDHCPAPI_PARAMS RecdParams;
LPBYTE RetDataList;
LPBYTE RetOptList;
DWORD nRecdParams;
DWORD Error;
DWORD i;
DWORD OutBufSize;
// check parameter consistency
if( NULL == AdapterName || NULL == RequestedOpt || 0 == nRequestedOpts )
return ERROR_INVALID_PARAMETER;
if( NULL == AvailOpts || 0 == nAvailOpts || NULL == OptData || 0 == OptDataSize )
return ERROR_INVALID_PARAMETER;
if( nRequestedOpts >= OPTION_END ) return ERROR_NO_SYSTEM_RESOURCES;
// initialize out params
(*nAvailOpts) = (*OptDataSize) = 0;
(*AvailOpts) = (*OptData) = NULL;
// try to process this request
SendParams.OptionId = (BYTE)OPTION_PARAMETER_REQUEST_LIST;
SendParams.IsVendor = FALSE;
SendParams.Data = RequestedOpt;
SendParams.nBytesData = nRequestedOpts;
nRecdParams = 0;
Error = DhcpRequestParameters(
AdapterName,
NULL,
0,
&SendParams,
1,
0,
NULL,
&nRecdParams
);
if( ERROR_MORE_DATA != Error ) return Error;
while ( TRUE ) {
DhcpAssert(nRecdParams);
DhcpPrint((DEBUG_OPTIONS, "RequestOptions: require: 0x%lx bytes\n", nRecdParams));
RecdParams = DhcpAllocateMemory(nRecdParams);
if( NULL == RecdParams ) return ERROR_NOT_ENOUGH_MEMORY;
Error = DhcpRequestParameters(
AdapterName,
NULL,
0,
&SendParams,
1,
0,
RecdParams,
&nRecdParams
);
// DhcpAssert(ERROR_MORE_DATA != Error);
if( ERROR_SUCCESS != Error ) {
DhcpPrint((DEBUG_ERRORS, "RequestOptions:RequestParams:0x%lx\n", Error));
DhcpFreeMemory(RecdParams);
if( ERROR_MORE_DATA == Error ) continue;
return Error;
}
break;
}
if( 0 == nRecdParams ) return ERROR_SUCCESS;
DhcpPrint((DEBUG_OPTIONS, "Received 0x%lx options\n", nRecdParams));
RetOptList = NULL;
RetDataList = NULL;
OutBufSize = 0;
for( i = 0; i < nRecdParams; i ++ ) {
DhcpPrint((DEBUG_TRACE, "Received option 0x%lx, 0x%lx bytes\n",
RecdParams[i].OptionId, RecdParams[i].nBytesData));
OutBufSize += RecdParams[i].nBytesData + sizeof(BYTE);
}
RetOptList = DhcpAllocateMemory(nRecdParams);
RetDataList = DhcpAllocateMemory(OutBufSize);
if( NULL == RetOptList || NULL == RetDataList ) {
if( RetOptList ) DhcpFreeMemory(RetOptList);
if( RetDataList ) DhcpFreeMemory(RetDataList);
if( RecdParams ) DhcpFreeMemory(RecdParams);
return ERROR_NOT_ENOUGH_MEMORY;
}
OutBufSize = 0;
for( i = 0; i < nRecdParams ; i ++ ) {
RetOptList[i] = (BYTE)RecdParams[i].OptionId;
RetDataList[OutBufSize++] = (BYTE)RecdParams[i].nBytesData;
memcpy(&RetDataList[OutBufSize], RecdParams[i].Data, RecdParams[i].nBytesData);
OutBufSize += RecdParams[i].nBytesData;
}
(*AvailOpts) = RetOptList;
(*nAvailOpts) = nRecdParams;
(*OptData) = RetDataList;
(*OptDataSize) = OutBufSize;
if( RecdParams ) DhcpFreeMemory(RecdParams);
return ERROR_SUCCESS;
}
DWORD // win32 status
DhcpRequestParamsInternalEx( // request parameters of client
IN BYTE OpCode, // opcode to use
IN LPWSTR AdapterName, // adapter name to request for
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id to use
IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
IN DWORD nSendParams, // size of above array
IN DWORD Flags, // must be zero, reserved
IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
IN OUT DWORD *pnRecdParams, // input: size of above array output: filled size
IN LPBYTE Bufp, // buffer for data ptrs
IN OUT LPDWORD pSize // i/p: size of above array, o/p filled size
)
{
PDHCP_API_ARGS DhcpApiArgs = NULL;
LPBYTE OutBuf;
LPBYTE InBuf = NULL;
LPBYTE Buffer;
LPBYTE Endp;
DWORD OutBufSize;
DWORD InBufSize;
DWORD i,j;
DWORD nArgsReturned;
DWORD Error;
DWORD nRecdParams = (*pnRecdParams);
DWORD nParamsRequested;
DWORD nVParamsRequested;
ULONG Tmp, VTmp;
CHAR TmpBuf[256], VTmpBuf[256];
// check parameter consistency
if( ClassIdLen && NULL == ClassId) return ERROR_INVALID_PARAMETER;
if( 0 == ClassIdLen && NULL != ClassId ) return ERROR_INVALID_PARAMETER;
if( nSendParams && NULL == SendParams) return ERROR_INVALID_PARAMETER;
if( 0 == nSendParams && NULL != SendParams) return ERROR_INVALID_PARAMETER;
if( NULL == RecdParams || 0 == nRecdParams ) return ERROR_INVALID_PARAMETER;
if( NULL == AdapterName ) return ERROR_INVALID_PARAMETER;
Tmp = VTmp = 0;
for( i = 0; i < nRecdParams ; i ++ ) {
if( FALSE == RecdParams[i].IsVendor ) {
TmpBuf[ ++Tmp] = (BYTE)RecdParams[i].OptionId;
} else {
VTmpBuf[ ++VTmp] = (BYTE)RecdParams[i].OptionId;
}
}
if( 0 == (VTmp + Tmp) ) return ERROR_INVALID_PARAMETER;
// allocate buffers
OutBufSize = (*pSize);
(*pSize) = 0;
if( 0 == OutBufSize ) OutBuf = NULL;
else {
OutBuf = Bufp;
}
// calculate input buffer size required
InBufSize = 0;
InBufSize += (DWORD)(sizeof(DWORD)*2); // INBUF_SIZE, OUTBUF_SIZE
InBufSize += (DWORD)(sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR));
if( ClassIdLen )
InBufSize += sizeof(BYTE)+sizeof(DWORD)+ClassIdLen;
for( i = 0; i < nSendParams; i ++ ) {
InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+SendParams[i].nBytesData;
}
//
// Now for options request list (vendor and otherwise)
//
if( Tmp ) {
InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+Tmp;
}
if( VTmp ) {
InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+VTmp;
}
InBuf = DhcpAllocateMemory(InBufSize);
if( NULL == InBuf ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
// fill up output buffer size right at start of input buffer
((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
((DWORD UNALIGNED*)InBuf)[1] = 0;
Buffer = InBuf + sizeof(DWORD);
InBufSize -= sizeof(DWORD);
// fill in input buffer
Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, OpCode);
DhcpAssert(ERROR_SUCCESS == Error);
if( ClassIdLen ) {
Error = DhcpApiArgAdd(Buffer, InBufSize, ClassIdParam, ClassIdLen, ClassId);
DhcpAssert(ERROR_SUCCESS == Error);
}
for( i = 0; i < nSendParams; i ++ ) {
BYTE Buf[OPTION_END+1];
BYTE OpCode;
Buf[0] = (BYTE)SendParams[i].OptionId;
memcpy(&Buf[1], SendParams[i].Data, SendParams[i].nBytesData);
OpCode = SendParams[i].IsVendor? VendorOptionParam: NormalOptionParam;
Error = DhcpApiArgAdd(Buffer, InBufSize, OpCode, SendParams[i].nBytesData+1, Buf);
DhcpAssert(ERROR_SUCCESS == Error);
}
//
// Now fillup the request lists (vendor & otherwise)
//
if( Tmp ) {
TmpBuf[0] = (BYTE)OPTION_PARAMETER_REQUEST_LIST;
Error = DhcpApiArgAdd(Buffer, InBufSize, NormalOptionParam, Tmp+1, TmpBuf);
DhcpAssert(ERROR_SUCCESS == Error);
}
if( VTmp ) {
VTmpBuf[0] = (BYTE)OPTION_PAD;
Error = DhcpApiArgAdd(Buffer, InBufSize, VendorOptionParam, VTmp+1, VTmpBuf);
}
// now, execute and obtain the output filled in OutBuf
Error = ExecuteApiRequest(InBuf, OutBuf, &OutBufSize);
(*pSize) = OutBufSize;
if( ERROR_MORE_DATA == Error ) {
// recalculate the real OutBufSize required
DhcpAssert(OutBufSize != 0);
goto Cleanup;
}
if( ERROR_SUCCESS != Error ) goto Cleanup;
if( 0 == OutBufSize ) goto Cleanup;
// parse output and fill in the structures..
nArgsReturned = 0;
DhcpApiArgs = NULL;
Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
DhcpAssert( 0 == nArgsReturned || ERROR_MORE_DATA == Error);
if( ERROR_MORE_DATA != Error ) goto Cleanup;
DhcpAssert(0 != nArgsReturned);
DhcpApiArgs = DhcpAllocateMemory( sizeof(DHCP_API_ARGS) * nArgsReturned);
if( NULL == DhcpApiArgs ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
DhcpAssert(ERROR_SUCCESS == Error);
DhcpAssert(nArgsReturned);
for(i = j = 0; i < nArgsReturned; i ++ ) {
DhcpAssert( VendorOptionParam == DhcpApiArgs[i].ArgId || NormalOptionParam == DhcpApiArgs[i].ArgId);
DhcpAssert( DhcpApiArgs[i].ArgSize > 1); // one byte for option id, and atleast one byte actual option
if( VendorOptionParam != DhcpApiArgs[i].ArgId && NormalOptionParam != DhcpApiArgs[i].ArgId )
continue;
RecdParams[j].OptionId = DhcpApiArgs[i].ArgVal[0];
RecdParams[j].IsVendor = ( VendorOptionParam == DhcpApiArgs[i].ArgId );
RecdParams[j].nBytesData = DhcpApiArgs[i].ArgSize-1;
RecdParams[j].Data = &DhcpApiArgs[i].ArgVal[1];
j ++;
}
(*pnRecdParams) = j;
Error = ERROR_SUCCESS;
Cleanup:
if( NULL != InBuf ) DhcpFreeMemory(InBuf);
if( NULL != DhcpApiArgs ) DhcpFreeMemory(DhcpApiArgs);
return Error;
}
DWORD // win32 status
DhcpRequestParamsInternal( // request parameters of client
IN BYTE OpCode, // opcode to use
IN LPWSTR AdapterName, // adapter name to request for
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id to use
IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
IN DWORD nSendParams, // size of above array
IN DWORD Flags, // must be zero, reserved
IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
IN OUT LPDWORD pnRecdParams // i/p: size of above in BYTES, o/p required or filled up size
) {
PDHCP_API_ARGS DhcpApiArgs = NULL;
LPBYTE OutBuf;
LPBYTE InBuf = NULL;
LPBYTE Buffer;
LPBYTE Endp;
DWORD OutBufSize;
DWORD InBufSize;
DWORD i,j;
DWORD nArgsReturned;
DWORD Error;
DWORD nParamsRequested;
DWORD nVParamsRequested;
ULONG Tmp, VTmp;
ULONG OriginalOutBufSize;
// check parameter consistency
if( ClassIdLen && NULL == ClassId) return ERROR_INVALID_PARAMETER;
if( 0 == ClassIdLen && NULL != ClassId ) return ERROR_INVALID_PARAMETER;
if( nSendParams && NULL == SendParams) return ERROR_INVALID_PARAMETER;
if( 0 == nSendParams && NULL != SendParams) return ERROR_INVALID_PARAMETER;
if( NULL == pnRecdParams ) return ERROR_INVALID_PARAMETER;
if( *pnRecdParams && NULL == RecdParams ) return ERROR_INVALID_PARAMETER;
if( NULL == AdapterName ) return ERROR_INVALID_PARAMETER;
Tmp = VTmp = 0;
for( i = 0; i < nSendParams ; i ++ ) {
if( SendParams[i].nBytesData > OPTION_END ) return ERROR_INVALID_PARAMETER;
if( SendParams[i].nBytesData && NULL == SendParams[i].Data )
return ERROR_INVALID_PARAMETER;
if( OPTION_PARAMETER_REQUEST_LIST == SendParams[i].OptionId ) {
if( SendParams[i].IsVendor ) continue;
nParamsRequested = SendParams[i].nBytesData;
Tmp ++;
}
if( OPTION_PAD == SendParams[i].OptionId ) {
if( !SendParams[i].IsVendor ) continue;
nVParamsRequested = SendParams[i].nBytesData;
VTmp ++;
}
}
if( 0 == (VTmp + Tmp) || 1 < VTmp || 1 < Tmp ) return ERROR_INVALID_PARAMETER;
if( 0 == Tmp) nParamsRequested = 0;
if( VTmp ) nParamsRequested += nVParamsRequested;
// allocate buffers
OriginalOutBufSize = OutBufSize = (*pnRecdParams);
(*pnRecdParams) = 0;
if( 0 == OutBufSize ) OutBuf = NULL;
else {
OutBuf = DhcpAllocateMemory(OutBufSize);
if( NULL == OutBuf ) return ERROR_NOT_ENOUGH_MEMORY;
}
// calculate input buffer size required
InBufSize = 0;
InBufSize += (DWORD)(sizeof(DWORD)*2); // INBUF_SIZE, OUTBUF_SIZE
InBufSize += (DWORD)(sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR));
if( ClassIdLen )
InBufSize += sizeof(BYTE)+sizeof(DWORD)+ClassIdLen;
for( i = 0; i < nSendParams; i ++ ) {
InBufSize += sizeof(BYTE)+sizeof(DWORD)+sizeof(BYTE)+SendParams[i].nBytesData;
}
InBuf = DhcpAllocateMemory(InBufSize);
if( NULL == InBuf ) {
DhcpFreeMemory(OutBuf);
return ERROR_NOT_ENOUGH_MEMORY;
}
// fill up output buffer size right at start of input buffer
((DWORD UNALIGNED*)InBuf)[0] = htonl(OutBufSize);
((DWORD UNALIGNED*)InBuf)[1] = 0;
Buffer = InBuf + sizeof(DWORD);
InBufSize -= sizeof(DWORD);
// fill in input buffer
Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, OpCode);
DhcpAssert(ERROR_SUCCESS == Error);
if( ClassIdLen ) {
Error = DhcpApiArgAdd(Buffer, InBufSize, ClassIdParam, ClassIdLen, ClassId);
DhcpAssert(ERROR_SUCCESS == Error);
}
for( i = 0; i < nSendParams; i ++ ) {
BYTE Buf[OPTION_END+1];
BYTE OpCode;
Buf[0] = (BYTE)SendParams[i].OptionId;
memcpy(&Buf[1], SendParams[i].Data, SendParams[i].nBytesData);
OpCode = SendParams[i].IsVendor? VendorOptionParam: NormalOptionParam;
Error = DhcpApiArgAdd(Buffer, InBufSize, OpCode, SendParams[i].nBytesData+1, Buf);
DhcpAssert(ERROR_SUCCESS == Error);
}
// now, execute and obtain the output filled in OutBuf
Error = ExecuteApiRequest(InBuf, OutBuf, &OutBufSize);
if( ERROR_MORE_DATA == Error ) {
// recalculate the real OutBufSize required
DhcpAssert(OutBufSize != 0);
OutBufSize += nParamsRequested*(sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD)));
(*pnRecdParams) = OutBufSize;
goto Cleanup;
}
if( ERROR_SUCCESS != Error ) goto Cleanup;
if( 0 == OutBufSize ) goto Cleanup;
// parse output and fill in the structures..
nArgsReturned = 0;
DhcpApiArgs = NULL;
Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
DhcpAssert( 0 == nArgsReturned || ERROR_MORE_DATA == Error);
if( ERROR_MORE_DATA != Error ) goto Cleanup;
DhcpAssert(0 != nArgsReturned);
DhcpApiArgs = DhcpAllocateMemory( sizeof(DHCP_API_ARGS) * nArgsReturned);
if( NULL == DhcpApiArgs ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
Error = DhcpApiArgDecode(OutBuf, OutBufSize, DhcpApiArgs, &nArgsReturned);
DhcpAssert(ERROR_SUCCESS == Error);
DhcpAssert(nArgsReturned);
if( OriginalOutBufSize < OutBufSize + nParamsRequested*(sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD)) ) ) {
//
// Input size is not sufficient
//
(*pnRecdParams ) = OutBufSize + nParamsRequested*(
sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD) )
);
Error = ERROR_MORE_DATA;
// DbgPrint("Bug 330419 repro'ed");
goto Cleanup;
}
Endp = OutBufSize + (LPBYTE)RecdParams + nParamsRequested*(sizeof(DHCPAPI_PARAMS) - (2*sizeof(BYTE)+sizeof(DWORD)));
for(i = j = 0; i < nArgsReturned; i ++ ) {
DhcpAssert( VendorOptionParam == DhcpApiArgs[i].ArgId || NormalOptionParam == DhcpApiArgs[i].ArgId);
DhcpAssert( DhcpApiArgs[i].ArgSize > 1); // one byte for option id, and atleast one byte actual option
if( VendorOptionParam != DhcpApiArgs[i].ArgId && NormalOptionParam != DhcpApiArgs[i].ArgId )
continue;
RecdParams[j].OptionId = DhcpApiArgs[i].ArgVal[0];
RecdParams[j].IsVendor = ( VendorOptionParam == DhcpApiArgs[i].ArgId );
RecdParams[j].nBytesData = DhcpApiArgs[i].ArgSize-1;
Endp -= RecdParams[j].nBytesData;
memcpy(Endp, &DhcpApiArgs[i].ArgVal[1], RecdParams[j].nBytesData);
RecdParams[j].Data = Endp;
j ++;
}
DhcpAssert(((LPBYTE)&RecdParams[j]) <= Endp);
*pnRecdParams = j;
Error = ERROR_SUCCESS;
Cleanup:
DhcpFreeMemory(InBuf);
if(OutBuf) DhcpFreeMemory(OutBuf);
if(DhcpApiArgs) DhcpFreeMemory(DhcpApiArgs);
return Error;
}
DWORD // win32 status
APIENTRY
DhcpRequestParameters( // request parameters of client
IN LPWSTR AdapterName, // adapter name to request for
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id to use
IN PDHCPAPI_PARAMS SendParams, // parameters to send to server
IN DWORD nSendParams, // size of above array
IN DWORD Flags, // must be zero, reserved
IN OUT PDHCPAPI_PARAMS RecdParams, // fill this array with received params
IN OUT LPDWORD pnRecdParams // i/p: size of above in BYTES, o/p required or filled up size
) {
return DhcpRequestParamsInternal(
RequestParamsOpCode,
AdapterName,
ClassId,
ClassIdLen,
SendParams,
nSendParams,
Flags,
RecdParams,
pnRecdParams
);
}
DWORD // win32 status
DhcpRegisterParameterChangeNotificationInternal( // notify if a parameter has changed -- common between NT and VxD
IN LPWSTR AdapterName, // adapter of interest
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id
IN PDHCPAPI_PARAMS Params, // params of interest
IN DWORD nParams, // # of elts in above array
IN DWORD Flags, // must be zero, reserved
IN DWORD Descriptor, // thsi describes the event uniquely for this process
IN HANDLE hEvent // handle to event that will be SetEvent'ed in case of param change
) {
LPBYTE InBuf;
LPBYTE OptList;
LPBYTE VendorOptList;
LPBYTE Buffer;
DWORD Error;
DWORD InBufSize;
DWORD nVendorOpts;
DWORD nOpts;
DWORD ProcId;
DWORD OutBufSize;
DWORD i;
VendorOptList = OptList = NULL;
nVendorOpts = nOpts = 0;
InBufSize = 2*sizeof(DWORD); // expected outbuf size + inbuf size
InBufSize += sizeof(BYTE) + 2*sizeof(DWORD); // Proc Id
InBufSize += sizeof(BYTE) + 2*sizeof(DWORD); // Event Handle
InBufSize += sizeof(BYTE) + 2*sizeof(DWORD); // Descriptor
InBufSize += (DWORD)(sizeof(Descriptor)+sizeof(hEvent)+sizeof(DWORD));
InBufSize += (DWORD)(sizeof(BYTE)+sizeof(DWORD)+(1+wcslen(AdapterName))*sizeof(WCHAR));
if( ClassIdLen )
InBufSize += sizeof(BYTE)+sizeof(DWORD)+ClassIdLen;
for( i = 0; i < nParams; i ++ ) {
if( OPTION_PARAMETER_REQUEST_LIST == Params[i].OptionId ) {
if( Params[i].IsVendor ) continue;
if( nOpts ) return ERROR_INVALID_PARAMETER;
nOpts = Params[i].nBytesData;
if( 0 == nOpts ) return ERROR_INVALID_PARAMETER;
OptList = Params[i].Data;
continue;
}
if( OPTION_PAD == Params[i].OptionId ) {
if( ! Params[i].IsVendor ) continue;
if( nVendorOpts ) return ERROR_INVALID_PARAMETER;
nVendorOpts = Params[i].nBytesData;
if( 0 == nVendorOpts ) return ERROR_INVALID_PARAMETER;
VendorOptList = Params[i].Data;
continue;
}
}
if( 0 == nOpts + nVendorOpts ) return ERROR_INVALID_PARAMETER;
if( nOpts ) InBufSize += sizeof(BYTE) + sizeof(DWORD) + nOpts;
if( nVendorOpts ) InBufSize += sizeof(BYTE) + sizeof(DWORD) + nVendorOpts;
InBuf = DhcpAllocateMemory(InBufSize);
if( NULL == InBuf ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
Buffer = InBuf + sizeof(DWORD);
((DWORD UNALIGNED*)InBuf)[0] = 0; // dont expect anything in return other than status
((DWORD UNALIGNED*)Buffer)[0] = 0; // increase the input buffer size each time we add something
InBufSize -= sizeof(DWORD); // ignore the first DWORD
Error = DhcpApiFillBuffer(Buffer, InBufSize, AdapterName, RegisterParamsOpCode);
DhcpAssert(ERROR_SUCCESS == Error );
if( ClassIdLen ) {
Error = DhcpApiArgAdd(Buffer, InBufSize, ClassIdParam, ClassIdLen, ClassId);
DhcpAssert(ERROR_SUCCESS == Error);
}
if( nOpts ) {
Error = DhcpApiArgAdd(Buffer, InBufSize, NormalOptionParam, nOpts, OptList);
DhcpAssert(ERROR_SUCCESS == Error);
}
if( nVendorOpts ) {
Error = DhcpApiArgAdd(Buffer, InBufSize, VendorOptionParam, nVendorOpts, VendorOptList);
DhcpAssert(ERROR_SUCCESS == Error);
}
ProcId = GetCurrentProcessId();
Error = DhcpApiArgAdd(Buffer, InBufSize, ProcIdParam, sizeof(ProcId), (LPBYTE) &ProcId);
DhcpAssert(ERROR_SUCCESS == Error);
Error = DhcpApiArgAdd(Buffer, InBufSize, DescriptorParam, sizeof(Descriptor), (LPBYTE) &Descriptor);
DhcpAssert(ERROR_SUCCESS == Error);
Error = DhcpApiArgAdd(Buffer, InBufSize, EventHandleParam, sizeof(hEvent), (LPBYTE) &hEvent);
DhcpAssert(ERROR_SUCCESS == Error);
OutBufSize = 0;
Error = ExecuteApiRequest(InBuf, NULL, &OutBufSize);
DhcpFreeMemory(InBuf);
DhcpAssert(ERROR_MORE_DATA != Error );
return Error;
}
DWORD // Ring 0 handle -- used only on win9x platform
VxDGetDescriptor( // convert Event to Ring0 handle for use in vdhcp.vxd
IN HANDLE Event,
IN OUT LPDWORD pDescriptor
) {
HANDLE Kernel32;
DWORD (*HandleToRing0Handle)(HANDLE);
DWORD RetVal;
Kernel32 = LoadLibraryA("kernel32.dll");
if( NULL == Kernel32 ) return GetLastError();
HandleToRing0Handle = (DWORD (*)(HANDLE))GetProcAddress(Kernel32, "OpenVxDHandle");
if( NULL == HandleToRing0Handle ) {
CloseHandle(Kernel32);
return GetLastError();
}
(*pDescriptor) = HandleToRing0Handle(Event);
CloseHandle(Kernel32);
if( 0 == (*pDescriptor) ) return ERROR_INVALID_PARAMETER;
return ERROR_SUCCESS;
}
DWORD // win32 status
DhcpCreateApiEventAndDescriptor( // create both the api event handle and the unique descriptor for it
IN OUT LPHANDLE hEvent, // fill this with a valid event handle if succeeded
IN OUT LPDWORD pDescriptor // this descriptor is unique for this process.
) {
static DWORD Descriptor = 1;// use this for the descriptor
OSVERSIONINFO OsVersion; // need to know if NT or Win95+
BOOL BoolError;
CHAR NameBuf[sizeof("DhcpPid-1-2-3-4-5-6-7-8UniqueId-1-2-3-4-5-6-7-8")];
DWORD Error;
// *** changing NameBuf's format requires change in apiimpl.c NotifyClients...*
OsVersion.dwOSVersionInfoSize = sizeof(OsVersion);
BoolError = GetVersionEx(&OsVersion);
if( FALSE == BoolError ) return GetLastError();
if( VER_PLATFORM_WIN32_WINDOWS == OsVersion.dwPlatformId ) {
(*hEvent) = CreateEvent(
NULL, // no security
FALSE, // auto reset
FALSE, // intially signaled? NO
NULL // no name
);
} else {
(*pDescriptor) = InterlockedIncrement(pDescriptor);
sprintf(NameBuf, "DhcpPid%16xUniqueId%16x", GetCurrentProcessId(), *pDescriptor);
(*hEvent) = CreateEventA( // now create the required event
NULL, // no security
FALSE, // automatic reset
FALSE, // intially signalled? NO!
NameBuf // the name to use to create
);
}
if( NULL == (*hEvent) ) return GetLastError();
if( VER_PLATFORM_WIN32_WINDOWS != OsVersion.dwPlatformId )
return ERROR_SUCCESS; // done for NT.
// for Memphis, need to get OpenVxdHandle procedure to get Descriptor value
Error = VxDGetDescriptor(*hEvent, pDescriptor);
if( ERROR_SUCCESS != Error ) {
CloseHandle(*hEvent);
}
return Error;
}
DWORD // win32 status
DhcpRegisterParameterChangeNotification( // notify if a parameter has changed
IN LPWSTR AdapterName, // adapter of interest
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id
IN PDHCPAPI_PARAMS Params, // params of interest
IN DWORD nParams, // # of elts in above array
IN DWORD Flags, // must be zero, reserved
IN OUT PHANDLE hEvent // handle to event that will be SetEvent'ed in case of param change
) {
DWORD Descriptor; // on NT this is an id unique across this process, on VxD ring0 handle
DWORD Error; //
DWORD i;
if( 0 == ClassIdLen && NULL != ClassId ) return ERROR_INVALID_PARAMETER;
if( 0 != ClassIdLen && NULL == ClassId ) return ERROR_INVALID_PARAMETER;
if( 0 == nParams && NULL != Params ) return ERROR_INVALID_PARAMETER;
if( 0 != nParams && NULL == Params ) return ERROR_INVALID_PARAMETER;
if( Flags ) return ERROR_INVALID_PARAMETER;
if( NULL == hEvent ) return ERROR_INVALID_PARAMETER;
for( i = 0; i < nParams ; i ++ ) {
if( Params[i].nBytesData > OPTION_END ) return ERROR_INVALID_PARAMETER;
if( Params[i].nBytesData && NULL == Params[i].Data )
return ERROR_INVALID_PARAMETER;
}
Error = DhcpCreateApiEventAndDescriptor(hEvent, &Descriptor);
if( ERROR_SUCCESS != Error ) return Error;
Error = DhcpRegisterParameterChangeNotificationInternal(
AdapterName,
ClassId,
ClassIdLen,
Params,
nParams,
Flags,
Descriptor,
(*hEvent)
);
if( ERROR_SUCCESS != Error ) {
CloseHandle(*hEvent);
*hEvent = NULL;
return Error;
}
return ERROR_SUCCESS;
}
DhcpDeRegisterParameterChangeNotification( // undo the registration
IN HANDLE Event // handle to event returned by DhcpRegisterParameterChangeNotification, NULL ==> everything
) {
DWORD Error;
DWORD Descriptor;
DWORD ProcId;
DWORD InBufSize;
DWORD OutBufSize;
LPBYTE InBuf;
LPBYTE Buffer;
InBufSize = 2*sizeof(DWORD); // input/output sizes
InBufSize += sizeof(BYTE) + sizeof(DWORD); // opcode
InBufSize += sizeof(BYTE) + sizeof(DWORD)*2; // proc id
InBufSize += sizeof(BYTE) + sizeof(DWORD)*2; // handle
InBuf = DhcpAllocateMemory(InBufSize);
if( NULL == InBuf ) return ERROR_NOT_ENOUGH_MEMORY;
Buffer = InBuf + sizeof(DWORD);
((DWORD UNALIGNED*)InBuf)[0] = 0; // nothing expected in return
((DWORD UNALIGNED*)Buffer)[0] = 0; // initialize size to zero -- will be increased each time something is added
Error = DhcpApiFillBuffer(Buffer, InBufSize, NULL, DeRegisterParamsOpCode);
DhcpAssert(ERROR_SUCCESS == Error);
ProcId = GetCurrentProcessId();
Error = DhcpApiArgAdd(Buffer, InBufSize, ProcIdParam, sizeof(ProcId), (LPBYTE)&ProcId);
DhcpAssert(ERROR_SUCCESS == Error);
Error = DhcpApiArgAdd(Buffer, InBufSize, EventHandleParam, sizeof(Event), (LPBYTE) &Event);
DhcpAssert(ERROR_SUCCESS == Error);
OutBufSize = 0;
Error = ExecuteApiRequest(InBuf, NULL, &OutBufSize);
DhcpFreeMemory(InBuf);
DhcpAssert(ERROR_MORE_DATA != Error);
if( ERROR_SUCCESS == Error ) {
CloseHandle(Event);
}
return Error;
}
DWORD // win32 status
DhcpRegistryFillParamsList( // read the registry value and add this list of values to it
IN LPWSTR AppName, // prefix for key
IN DWORD nSendParams // # of values to add
) {
HKEY DhcpOptionKey;
LPWSTR OldValueName;
LPWSTR NewValueName;
LPWSTR ValueName;
LPWSTR Tmp, Tmp2;
BOOL fOldValueExists = FALSE;
DWORD ValueNameSize;
DWORD OldValueNameSize;
DWORD NewValueNameSize;
DWORD Error;
DWORD i;
Error = RegOpenKeyEx( // open the dhcp option key first
HKEY_LOCAL_MACHINE,
DHCP_CLIENT_OPTION_KEY,
0 /* Reserved */,
DHCP_CLIENT_KEY_ACCESS,
&DhcpOptionKey
);
if( ERROR_SUCCESS != Error ) return Error;
OldValueName = NULL;
Error = GetRegistryString(
DhcpOptionKey,
DHCP_OPTION_LIST_VALUE,
&OldValueName,
&OldValueNameSize
);
if( ERROR_SUCCESS != Error ) {
OldValueName = DEFAULT_DHCP_KEYS_LIST_VALUE;
OldValueNameSize = sizeof(DEFAULT_DHCP_KEYS_LIST_VALUE);
} else {
fOldValueExists = TRUE;
}
NewValueNameSize = OldValueNameSize;
ValueNameSize = 0;
ValueNameSize += wcslen(AppName)*sizeof(WCHAR);
ValueNameSize += sizeof(L"\\12345");
ValueName = DhcpAllocateMemory(ValueNameSize);
if( NULL == ValueName ) {
RegCloseKey(DhcpOptionKey);
if( fOldValueExists ) DhcpFreeMemory(OldValueName);
return ERROR_NOT_ENOUGH_MEMORY;
}
NewValueNameSize = nSendParams*ValueNameSize + OldValueNameSize;
NewValueName = DhcpAllocateMemory(NewValueNameSize);
if( NULL == NewValueName ) {
RegCloseKey(DhcpOptionKey);
if( fOldValueExists ) DhcpFreeMemory(OldValueName);
DhcpFreeMemory(ValueName);
return ERROR_NOT_ENOUGH_MEMORY;
}
wcscpy(ValueName, AppName);
wcscat(ValueName, L"\\");
Tmp = NewValueName;
for( i = 0; i < nSendParams ; i ++ ) { // for each value, add its to the list
wcscpy(Tmp, ValueName);
Tmp += wcslen(Tmp);
swprintf(Tmp, L"%5x", i);
Tmp += wcslen(Tmp);
Tmp ++; // move the ptr off the last L'\0'
}
DhcpFreeMemory(ValueName);
Tmp2 = OldValueName;
while(wcslen(Tmp2)) {
wcscpy(Tmp, Tmp2);
Tmp += wcslen(Tmp2);
Tmp2 += wcslen(Tmp2);
Tmp ++;
Tmp2 ++;
}
*Tmp++ = L'\0';
if(fOldValueExists ) DhcpFreeMemory(OldValueName);
Error = RegSetValueEx( // write this string back
DhcpOptionKey,
DHCP_OPTION_LIST_VALUE,
0 /* Reserved */,
REG_MULTI_SZ,
(LPBYTE) NewValueName,
(ULONG)(((LPBYTE)Tmp) - ((LPBYTE)NewValueName))
);
DhcpFreeMemory(NewValueName);
RegCloseKey(DhcpOptionKey);
if( ERROR_SUCCESS != Error ) {
DhcpPrint((DEBUG_ERRORS, "RegSetValueEx(OPTION_LIST):0x%lx\n", Error));
}
return Error;
}
DWORD // win32 status
DhcpRegistryFillParams( // make a subkey and fill in the details
IN LPWSTR AdapterName, // NULL ==> global change
IN LPBYTE ClassId, // this is the class of the option
IN DWORD ClassIdLen, // # of bytes of above
IN DWORD i, // key index is 3hex-digit convertion onf this
IN HKEY Key, // use this key for creating subkeys
IN PDHCPAPI_PARAMS SendParam, // ptr to structure to use for this one key write operation
IN LPWSTR AppName // name of app
) {
HKEY SubKey;
WCHAR KeyName[7]; // key is just 5 bytes
LPWSTR SendLocation;
LPWSTR ValueName;
LPBYTE SendData;
DWORD SendDataSize;
DWORD Size;
DWORD Disposition;
DWORD Error;
DWORD OptionId;
DWORD IsVendor;
DWORD DummyKeyType;
swprintf(KeyName, L"%5x", i);
OptionId = SendParam->OptionId;
IsVendor = SendParam->IsVendor;
SendData = SendParam->Data;
SendDataSize = SendParam->nBytesData;
Size = wcslen(AppName)*sizeof(WCHAR)+sizeof(KeyName) + sizeof(L"\\");
if( AdapterName ) {
Size += (DWORD)(sizeof(DHCP_SERVICES_KEY) + sizeof(DHCP_ADAPTER_PARAMETERS_KEY) + wcslen(AdapterName)*sizeof(WCHAR));
} else {
Size += sizeof(DHCP_TCPIP_PARAMETERS_KEY);
}
SendLocation = DhcpAllocateMemory(Size);
if( NULL == SendLocation ) return ERROR_NOT_ENOUGH_MEMORY;
if( AdapterName ) {
wcscpy(SendLocation, DHCP_SERVICES_KEY DHCP_ADAPTER_PARAMETERS_KEY);
wcscat(SendLocation, L"\\?\\");
} else {
wcscpy(SendLocation, DHCP_TCPIP_PARAMETERS_KEY);
}
wcscat(SendLocation, AppName);
wcscat(SendLocation, KeyName);
Error = RegCreateKeyEx( // create the option key
Key,
KeyName,
0 /* Reserved */,
DHCP_CLASS,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&SubKey,
&Disposition
);
if( ERROR_SUCCESS != Error ) {
DhcpFreeMemory(SendLocation);
return Error;
}
DhcpAssert(REG_CREATED_NEW_KEY == Disposition);
Error = RegSetValueEx( // now create each of the values -- OPTION ID
SubKey,
DHCP_OPTION_OPTIONID_VALUE,
0 /* Reserved */,
DHCP_OPTION_OPTIONID_TYPE,
(LPBYTE)&OptionId,
sizeof(OptionId)
);
DhcpAssert(ERROR_SUCCESS == Error);
Error = RegSetValueEx( // IS VENDOR
SubKey,
DHCP_OPTION_ISVENDOR_VALUE,
0 /* Reserved */,
DHCP_OPTION_ISVENDOR_TYPE,
(LPBYTE) (&IsVendor),
sizeof(IsVendor)
);
DhcpAssert(ERROR_SUCCESS == Error);
if( ClassIdLen ) {
Error = RegSetValueEx( // CLASS ID
SubKey,
DHCP_OPTION_CLASSID_VALUE,
0 /* Reserved */,
REG_BINARY,
ClassId,
ClassIdLen
);
DhcpAssert(ERROR_SUCCESS == Error);
}
Error = RegSetValueEx(
SubKey,
DHCP_OPTION_SEND_LOCATION_VALUE,
0 /* Reserved */,
REG_SZ,
(LPBYTE)SendLocation,
(wcslen(SendLocation)+1)*sizeof(WCHAR)
);
DhcpAssert(ERROR_SUCCESS == Error);
DummyKeyType = REG_DWORD; // KeyType
Error = RegSetValueEx(
SubKey,
DHCP_OPTION_SAVE_TYPE_VALUE,
0 /* Reserved */,
DHCP_OPTION_SAVE_TYPE_TYPE,
(LPBYTE)&DummyKeyType,
sizeof(DummyKeyType));
DhcpAssert(ERROR_SUCCESS == Error);
RegCloseKey(SubKey);
if( AdapterName ) {
wcscpy(SendLocation, DHCP_SERVICES_KEY DHCP_ADAPTER_PARAMETERS_KEY);
wcscat(SendLocation, L"\\");
wcscat(SendLocation, AdapterName);
} else {
wcscpy(SendLocation, DHCP_TCPIP_PARAMETERS_KEY);
}
ValueName = wcslen(SendLocation) + 1 + SendLocation;
wcscpy(ValueName, AppName);
wcscat(ValueName, KeyName);
Error = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
SendLocation,
0 /* Reserved */,
KEY_ALL_ACCESS,
&SubKey
);
if( ERROR_SUCCESS != Error ) {
DhcpFreeMemory(SendLocation);
return Error;
}
Error = RegSetValueEx(
SubKey,
ValueName,
0 /* Reserved */,
REG_BINARY,
SendData,
SendDataSize
);
DhcpAssert(ERROR_SUCCESS == Error);
RegCloseKey(SubKey);
DhcpFreeMemory(SendLocation);
return ERROR_SUCCESS;
}
DWORD // win32 status
DhcpRegistryCreateUniqueKey( // create a unique key with prefix AppName
IN LPWSTR AppName, // some App descriptor
IN OUT HKEY* Key // return the opened key here
) {
DWORD FullKeyNameSize, Disposition;
DWORD Error;
LPWSTR FullKeyName;
FullKeyNameSize = sizeof(DHCP_CLIENT_OPTION_KEY);
FullKeyNameSize += wcslen(AppName)*sizeof(WCHAR) + sizeof(WCHAR);
FullKeyName = DhcpAllocateMemory(FullKeyNameSize);
if( NULL == FullKeyName ) return ERROR_NOT_ENOUGH_MEMORY;
wcscpy(FullKeyName, DHCP_CLIENT_OPTION_KEY);
wcscat(FullKeyName, L"\\");
wcscat(FullKeyName, AppName);
Error = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
FullKeyName,
0 /* Reserved */,
DHCP_CLASS,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
Key,
&Disposition
);
DhcpFreeMemory(FullKeyName);
if( ERROR_SUCCESS != Error ) return Error;
if( REG_OPENED_EXISTING_KEY == Disposition ) {
RegCloseKey(*Key);
return ERROR_ALREADY_EXISTS;
}
return ERROR_SUCCESS;
}
DWORD // win32 status
DhcpRegistryPersistentRequestParams( // edit registry to consider this additional persistent request
IN LPWSTR AdapterName, // which adapter is this request for?
IN LPBYTE ClassId, // class
IN DWORD ClassIdLen, // # of bytes in class id
IN PDHCPAPI_PARAMS SendParams, // the actual parameters to fill up
IN DWORD nSendParams, // the size of the above array
IN PDHCPAPI_PARAMS RecdParams, // would like to receive these
IN DWORD nRecdParams, // count..
IN LPWSTR AppName // some thing unique about the app that wants to do registrations
) {
HKEY Key;
DWORD i;
DWORD Error;
DWORD LastError;
DHCPAPI_PARAMS NonVendorParams;
ULONG nVendorOpt, nNonVendorOpt;
CHAR Buf[256];
if( NULL == AppName ) return ERROR_INVALID_PARAMETER;
if( 0 == nSendParams && NULL != SendParams ) return ERROR_INVALID_PARAMETER;
if( 0 != nSendParams && NULL == SendParams ) return ERROR_INVALID_PARAMETER;
if( 0 != nRecdParams && NULL == RecdParams ) return ERROR_INVALID_PARAMETER;
if( 0 == nRecdParams && NULL != RecdParams ) return ERROR_INVALID_PARAMETER;
if( ClassIdLen && NULL == ClassId || 0 == ClassIdLen && NULL != ClassId)
return ERROR_INVALID_PARAMETER;
for( i = 0; i < nSendParams; i ++ ) {
if( SendParams[i].nBytesData == 0 ) return ERROR_INVALID_PARAMETER;
}
nVendorOpt = nNonVendorOpt = 0;
// --ft: 07/25/00 fixes the way the non-vendor options
// are collected from RecdParams.
for (i = 0; i < nRecdParams; i++)
{
if (RecdParams[i].IsVendor)
{
nVendorOpt = 1;
}
else
{
Buf[nNonVendorOpt++] = (BYTE)RecdParams[i].OptionId;
}
}
// if nVendorOpt is 1 this means we have at least one vendor option in
// the requested parameters list. Make sure then OPTION_VENDOR_SPEC_INFO
// is mentioned in the array to be sent as OPTION_PARAMETER_REQUEST_LIST
if( nVendorOpt ) {
for( i = 0; i < nNonVendorOpt ; i ++ )
if( Buf[i] == OPTION_VENDOR_SPEC_INFO )
break;
if( i == nNonVendorOpt ) Buf[nNonVendorOpt ++] = (BYTE)OPTION_VENDOR_SPEC_INFO;
}
NonVendorParams.Flags = 0;
NonVendorParams.OptionId = OPTION_PARAMETER_REQUEST_LIST;
NonVendorParams.IsVendor = FALSE;
NonVendorParams.Data = Buf;
NonVendorParams.nBytesData = nNonVendorOpt;
Error = DhcpRegistryCreateUniqueKey( // first try creating the key
AppName,
&Key
);
if( ERROR_SUCCESS != Error ) return Error;
Error = DhcpRegistryFillParamsList(
AppName,
nSendParams + (nNonVendorOpt?1:0)
);
if( ERROR_SUCCESS != Error ) {
DhcpAssert(FALSE);
DhcpPrint((DEBUG_ERRORS, "DhcpRegistryFillParamsList:0x%lx\n", Error));
RegCloseKey(Key);
return Error;
}
LastError = ERROR_SUCCESS;
for( i = 0; i < nSendParams; i ++ ) { // now enter the particular option in the registry
Error = DhcpRegistryFillParams(
AdapterName,
ClassId,
ClassIdLen,
i,
Key,
&SendParams[i],
AppName
);
if( ERROR_SUCCESS != Error ) {
DhcpAssert(FALSE);
DhcpPrint((DEBUG_ERRORS, "DhcpRegistryFillParams:0x%lx\n", Error));
LastError = Error;
}
}
if( nNonVendorOpt ) {
Error = DhcpRegistryFillParams(
AdapterName,
ClassId,
ClassIdLen,
i ++,
Key,
&NonVendorParams,
AppName
);
if( ERROR_SUCCESS != Error ) {
DhcpAssert(FALSE);
DhcpPrint((DEBUG_ERRORS, "DhcpRegistryFillParams:0x%lx\n", Error));
LastError = Error;
}
}
RegCloseKey(Key);
return LastError;
}
// Please note that AppName must be unique for each request (and if it is not, things are
// likely to behave weirdly.. This is the same name that should be used for the deletion..
DWORD // win32 status
DhcpPersistentRequestParams( // parameters to request persistently
IN LPWSTR AdapterName, // adapter name to request for
IN LPBYTE ClassId, // byte stream of class id to use
IN DWORD ClassIdLen, // # of bytes of class id
IN PDHCPAPI_PARAMS SendParams, // persistent parameters
IN DWORD nSendParams, // size of above array
IN DWORD Flags, // must be zero, reserved
IN LPWSTR AppName // name of app doing the persistent request
) {
DWORD Error;
DWORD nRecdParams;
nRecdParams = 0;
Error = DhcpRequestParamsInternal(
PersistentRequestParamsOpCode,
AdapterName,
ClassId,
ClassIdLen,
SendParams,
nSendParams,
Flags,
NULL,
&nRecdParams
);
DhcpAssert(ERROR_MORE_DATA != Error );
if( ERROR_INVALID_PARAMETER == Error ) Error = ERROR_SUCCESS; // see below comment
if( ERROR_SUCCESS != Error ) { // if AdapterName is NULL or if ClassId is not the one currently in use
return Error; // only then do we get ERROR_INVALID_PARAMETER -- so filter those out
}
return DhcpRegistryPersistentRequestParams( // now munge the registry
AdapterName,
ClassId,
ClassIdLen,
SendParams,
nSendParams,
NULL,
0,
AppName
);
}
DWORD // win32 status
DhcpDelPersistentRequestParams( // undo the effect of a persistent request -- currently undo from registry
IN LPWSTR AdapterName, // the name of the adpater to delete for
IN LPWSTR AppName // the name used by the app
) {
HKEY Key;
DWORD Error;
DWORD LocationSize;
DWORD FullKeyNameSize, Disposition;
LPWSTR FullKeyName;
LPWSTR LocationValue;
LPWSTR Tmp, Tmp2;
FullKeyNameSize = sizeof(DHCP_CLIENT_OPTION_KEY);
FullKeyNameSize += wcslen(AppName)*sizeof(WCHAR) + sizeof(WCHAR);
FullKeyName = DhcpAllocateMemory(FullKeyNameSize);
if( NULL == FullKeyName ) return ERROR_NOT_ENOUGH_MEMORY;
wcscpy(FullKeyName, DHCP_CLIENT_OPTION_KEY);
wcscat(FullKeyName, L"\\");
wcscat(FullKeyName, AppName);
Error = DhcpRegRecurseDelete(HKEY_LOCAL_MACHINE, FullKeyName);
DhcpAssert(ERROR_SUCCESS == Error);
DhcpFreeMemory(FullKeyName);
Error = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
DHCP_CLIENT_OPTION_KEY,
0 /* Reserved */,
DHCP_CLIENT_KEY_ACCESS,
&Key
);
if( ERROR_SUCCESS != Error ) {
DhcpAssert(FALSE);
return Error;
} else {
DhcpRegRecurseDelete(Key, AppName);
}
LocationValue = NULL;
Error = GetRegistryString( // read the value
Key,
DHCP_OPTION_LIST_VALUE,
&LocationValue,
&LocationSize
);
if( LocationValue == NULL ) Error = ERROR_FILE_NOT_FOUND;
if( ERROR_SUCCESS != Error ) {
RegCloseKey(Key);
return Error;
}
Tmp = Tmp2 = LocationValue;
while(wcslen(Tmp) ) {
if( 0 != wcsncmp(AppName, Tmp, wcslen(AppName))) {
wcscpy(Tmp2, Tmp);
Tmp2 += wcslen(Tmp) +1;
Tmp += wcslen(Tmp) +1;
continue;
}
if( Tmp[wcslen(AppName)] != L'\\' ) {
wcscpy(Tmp2, Tmp);
Tmp2 += wcslen(Tmp) +1;
Tmp += wcslen(Tmp) +1;
continue;
}
//
// found required entry.. just skip over it..
//
Tmp += wcslen(Tmp) +1;
}
*Tmp2 ++ = L'\0';
Error = RegSetValueEx(
Key,
DHCP_OPTION_LIST_VALUE,
0 /* Reserved */,
REG_MULTI_SZ,
(LPBYTE)LocationValue,
(ULONG)(((LPBYTE)Tmp2 - (LPBYTE)LocationValue))
);
RegCloseKey(Key);
DhcpFreeMemory(LocationValue);
return Error;
}
BOOL _inline
CharInMem(
IN BYTE Byte,
IN LPBYTE Mem,
IN ULONG MemSz
)
{
while(MemSz) {
if( Byte == *Mem ) return TRUE;
Mem ++; MemSz --;
}
return FALSE;
}
DWORD
APIENTRY
DhcpRegisterOptions(
IN LPWSTR AdapterName,
IN LPBYTE OptionList,
IN DWORD OptionListSz,
IN HANDLE *pdwHandle
) {
DHCPAPI_PARAMS DhcpParams;
DWORD Error;
DHCP_OPTION DummyOption;
LPBYTE Value;
DWORD ValueSize, ValueType;
BYTE Buf[256];
ULONG nElementsInBuf;
DhcpParams.OptionId = OPTION_PARAMETER_REQUEST_LIST;
DhcpParams.IsVendor = FALSE;
DhcpParams.Data = OptionList;
DhcpParams.nBytesData = OptionListSz;
Error = DhcpRegisterParameterChangeNotification(
AdapterName,
NULL,
0,
&DhcpParams,
1,
0,
pdwHandle
);
if( ERROR_SUCCESS != Error ) return Error;
memset(&DummyOption, 0, sizeof(DummyOption));
Value = NULL; ValueSize = 0;
Error = DhcpRegReadFromAnyLocation(
DHCP_REGISTER_OPTIONS_LOC,
AdapterName,
&Value,
&ValueType,
&ValueSize
);
if( ERROR_SUCCESS == Error && REG_BINARY == ValueType && 0 != ValueSize ) {
//
// Got some pre-existing values... add the remaining to it..
//
memcpy(Buf, Value, ValueSize);
while(OptionListSz) {
if( !CharInMem(*OptionList, Value, ValueSize) )
Buf[ValueSize++] = *OptionList;
OptionList ++; OptionListSz --;
}
OptionList = Buf;
OptionListSz = ValueSize;
}
if( NULL != Value ) DhcpFreeMemory(Value);
DummyOption.Data = OptionList;
DummyOption.DataLen = OptionListSz;
Error = DhcpRegSaveOptionAtLocationEx(
&DummyOption,
AdapterName,
DHCP_REGISTER_OPTIONS_LOC,
REG_BINARY
);
return Error;
}
DWORD
APIENTRY
DhcpDeRegisterOptions (
IN HANDLE OpenHandle
) {
DWORD Error;
Error = DhcpDeRegisterParameterChangeNotification(OpenHandle);
if( ERROR_SUCCESS != Error ) return Error;
//
// can't undo registry as we don't have enough information to do that.
//
return Error;
}
//================================================================================
// C L I E N T A P I E N T R Y P O I N T S
//================================================================================
DWORD
APIENTRY
DhcpCApiInitialize(
OUT LPDWORD Version
)
/*++
Routine Description:
This routine intializes all the DHCP Client side APIs
Arguemnts:
Version - a pointer to a DWORD that gets filled with DHCP APIs version #.
Return Value:
Returns STatus.
--*/
{
if( NULL != Version ) *Version = 2;
return ERROR_SUCCESS;
}
VOID
APIENTRY
DhcpCApiCleanup(
VOID
)
/*++
Routine Description:
This routine cleansup afterall the DHCP Client side APIs have been called.
--*/
{
return ;
}
DWORD // win32 status
APIENTRY
DhcpRequestParams( // request parameters of client
IN DWORD Flags, // must be DHCPCAPI_REQUEST_SYNCHRONOUS
IN LPVOID Reserved, // this parameter is reserved
IN LPWSTR AdapterName, // adapter name to request for
IN LPDHCPCAPI_CLASSID ClassId, // reserved must be NULL
IN DHCPCAPI_PARAMS_ARRAY SendParams, // parameters to send.
IN OUT DHCPCAPI_PARAMS_ARRAY RecdParams, // parameters that are to be requested..
IN LPBYTE Buffer, // a buffer to hold data for RecdParams
IN OUT LPDWORD pSize, // i/p: size of above in BYTES, o/p required bytes..
IN LPWSTR RequestIdStr // name of the application, unique per request
) // returns ERROR_MORE_DATA if o/p buffer is of insufficient size, and fills in reqd size in # of bytes
/*++
Routine Description:
This routine can be used to do Request options from the DHCP Server and based on
whether then whether the request is permanent or not, this request would be stored
in the registry for persistence across boots. The requests can have a particular class
for which they'd be defined... (the class is sent on wire for the server to decide
which options to send). The request could be ASYNCHRONOUS in the sense that the call
returns even before the server returns the data.. But this is not yet implemented.
Arugments:
Flags - currently DHCPCAPI_REQUEST_SYNCHRONOUS must be defined.
if a persisten request is desired, DHCPCAPI_REQUEST_PERSISTENT can
also be passed (bit-wise OR'ed)
Reserved - MUST be NULL. Reserved for future USE.
AdapterName - The Name of the adapter for which this request is designed. This
cannot be NULL currently though it is a nice thing to implement for
future.
ClassId - The binary ClassId information to use to send on wire.
SendParams - The Parameters to actual send on wire.
RecdParams - The parameters to be received back from the DHCP server
Buffer - A buffer to hold some information. This cannot be NULL and some
pointers within the RecdParams structure use this buffer, so it cannot
be deallocated so long as the RecdParams array is in USE.
pSize - This is (on input) the size in bytes of the Buffer variable. When
the function returns ERROR_MORE_DATA, this variable would be the size
in bytes required. If the function returns SUCCESSFULLY, this would
be the number of bytes space used up in reality.
RequestIdStr - a string identifying the request being made. This has to be unique
to each request (and a Guid is suggested). This string is needed to
undo the effects of a RequestParam via UndoRequestParams..
Return Value:
This function returns ERROR_MORE_DATA if the buffer space provided by "Buffer" variable
is not sufficient. (In this case, the pSize variable is filled in with the actual
size required). On success it returns ERROR_SUCCESS. Otherwise, it returns Win32
status.
--*/
{
ULONG Error;
ULONG i;
//
// Parameter validation
//
if( Flags != DHCPCAPI_REQUEST_SYNCHRONOUS &&
Flags != DHCPCAPI_REQUEST_PERSISTENT &&
Flags != (DHCPCAPI_REQUEST_SYNCHRONOUS | DHCPCAPI_REQUEST_PERSISTENT)) {
return ERROR_INVALID_PARAMETER;
}
if( NULL != Reserved || NULL == AdapterName ||
0 == RecdParams.nParams || NULL == pSize ) {
return ERROR_INVALID_PARAMETER;
}
if( NULL == Buffer && *pSize ) {
return ERROR_INVALID_PARAMETER;
}
if( NULL != ClassId ) {
if( 0 != ClassId->Flags ) return ERROR_INVALID_PARAMETER;
if( NULL == ClassId->Data || 0 == ClassId->nBytesData ) {
return ERROR_INVALID_PARAMETER;
}
}
if( NULL == RecdParams.Params || (0 != SendParams.nParams && NULL == SendParams.Params) ) {
return ERROR_INVALID_PARAMETER;
}
for( i = 0; i < RecdParams.nParams ; i ++ ) {
if( 0 != RecdParams.Params[i].nBytesData ||
NULL != RecdParams.Params[i].Data ) {
return ERROR_INVALID_PARAMETER;
}
}
//
// Now call the DhcpRequestParameters API and do datatype conversions for that..
//
Error = ERROR_SUCCESS;
if( Flags & DHCPCAPI_REQUEST_SYNCHRONOUS ) {
Error = DhcpRequestParamsInternalEx(
RequestParamsOpCode,
AdapterName,
ClassId? ClassId->Data : NULL,
ClassId? ClassId->nBytesData : 0,
SendParams.Params,
SendParams.nParams,
0,
RecdParams.Params,
&RecdParams.nParams,
Buffer,
pSize
);
}
if( ERROR_SUCCESS != Error ) return Error;
if( Flags & DHCPCAPI_REQUEST_PERSISTENT ) {
Error = DhcpRegistryPersistentRequestParams(
AdapterName,
ClassId? ClassId->Data : NULL,
ClassId? ClassId->nBytesData : 0,
SendParams.Params,
SendParams.nParams,
RecdParams.Params,
RecdParams.nParams,
RequestIdStr
);
}
return Error;
}
DWORD // win32 status
APIENTRY
DhcpUndoRequestParams( // undo the effect of a persistent request -- currently undo from registry
IN DWORD Flags, // must be zero, reserved
IN LPVOID Reserved, // this parameter is reserved
IN LPWSTR AdapterName, // the original adapter this was registerdd for,..
IN LPWSTR RequestIdStr // the requestId str passed to RequestParams..
)
/*++
Routine Description:
This function is used to undo the effects of a persistent request done
via DhcpRequestParams with DHCPCAPI_REQUEST_PERSISTENT option.
Arguments:
Flags - MUST be zero. Reserved for future use.
Reserved - MUST be NULL
AdapterName - The original adapter name this request was made for
RequestIdStr - The original request Id string passed to RequestParams
Return Value:
returns Win32 status
--*/
{
if( 0 != Flags || NULL != Reserved || NULL == RequestIdStr )
return ERROR_INVALID_PARAMETER;
return DhcpDelPersistentRequestParams(
AdapterName,
RequestIdStr
);
}
DWORD // win32 status
APIENTRY
DhcpRegisterParamChange( // notify if a parameter has changed
IN DWORD Flags, // must be DHCPCAPI_REGISTER_HANDLE_EVENT
IN LPVOID Reserved, // this parameter is reserved
IN LPWSTR AdapterName, // adapter of interest
IN LPDHCPCAPI_CLASSID ClassId, // reserved must be NULL
IN DHCPCAPI_PARAMS_ARRAY Params, // parameters of interest
IN OUT LPVOID Handle // handle to event that will be SetEvent'ed in case of param change
)
/*++
Routine Description;
This function registers with DHCP for any notifications on changes to the
specified options.. (notifications are via an EVENT handle)
Arguments:
Flags - this decides how the notification works -- via EVENTS or otherwise.
Currently, only event based mechanism is provided. So, this must be
DHCPCAPI_REGISTER_HANDLE_EVENT. In this case, Handle must also
be the address of a handle variable. (This is not the event handle
itself, the event handle is returned in this address).
Reserved - MUST be NULL.
AdapterName - MUST NOT BE NULL. This is the name of the adapter for which the
notification is being registered..
ClassId - This specifies the classId if any for which the registration is.
Params - This is the set of parameter to listen on and notify of when any
change happens..
Handle - See "Flags" for what this variable is.
Return values:
returns Win32 status codes
--*/
{
DWORD Error;
CHAR Buf[256]; // cannot request more options than this!
CHAR VBuf[256];
DHCPAPI_PARAMS Param[2], *pReqParams;
ULONG i;
DWORD nOpt, nVOpt;
if( Flags != DHCPCAPI_REGISTER_HANDLE_EVENT ) {
return ERROR_INVALID_PARAMETER;
}
if( NULL != Reserved || NULL == AdapterName || 0 == Params.nParams || NULL == Handle ) {
return ERROR_INVALID_PARAMETER;
}
nOpt = nVOpt = 0;
for( i = 0; i < Params.nParams ; i ++ ) {
if( Params.Params[i].IsVendor ) {
VBuf[nVOpt++] = (BYTE)Params.Params[i].OptionId;
} else {
Buf[nOpt++] = (BYTE)Params.Params[i].OptionId;
}
}
Param[0].OptionId = OPTION_PARAMETER_REQUEST_LIST;
Param[0].IsVendor = FALSE;
Param[0].Data = Buf;
Param[0].nBytesData = nOpt;
Param[1].OptionId = OPTION_PAD;
Param[1].IsVendor = TRUE;
Param[1].Data = VBuf;
Param[1].nBytesData = nVOpt;
if( 0 == nOpt ) pReqParams = &Param[1]; else pReqParams = &Param[0];
return DhcpRegisterParameterChangeNotification(
AdapterName,
ClassId? ClassId->Data : NULL,
ClassId? ClassId->nBytesData : 0,
pReqParams,
(nOpt != 0) + (nVOpt != 0),
0,
Handle
);
}
DWORD
APIENTRY
DhcpDeRegisterParamChange( // undo the registration
IN DWORD Flags, // MUST BE ZERO --> No flags yet.
IN LPVOID Reserved, // MUST BE NULL --> Reserved
IN LPVOID Event // handle to event returned by DhcpRegisterParamChange.
)
/*++
Routine description:
This routine undoes whateve was done by previous routine, and closes the
handle also. The handle cannot be used after this.
Arguments:
Flags - MUST BE DHCPCAPI_REGISTER_HANDLE_EVENT currently.
Reserved - MuST BE NULL
Event - this is the event handle returned in the "Handle" parameter to
DhcpRegisterParamChange function.
Return Value:
Win32 status
--*/
{
return DhcpDeRegisterParameterChangeNotification(Event);
}
DWORD
APIENTRY
DhcpRemoveDNSRegistrations(
VOID
)
{
return DhcpAdapterOnlyApi(NULL, RemoveDNSRegistrationsOpCode);
}
//================================================================================
// end of file
//================================================================================
#endif H_ONLY