|
|
//================================================================================
// Copyright (C) 1997 Microsoft Corporation
// Author: RameshV
// Description: most of the rpc apis are here and some miscellaneous functions too
// all the functions here go to the DS directly.
//================================================================================
#include <hdrmacro.h>
#include <store.h>
#include <dhcpmsg.h>
#include <wchar.h>
#include <dhcpbas.h>
#include <mm\opt.h>
#include <mm\optl.h>
#include <mm\optdefl.h>
#include <mm\optclass.h>
#include <mm\classdefl.h>
#include <mm\bitmask.h>
#include <mm\reserve.h>
#include <mm\range.h>
#include <mm\subnet.h>
#include <mm\sscope.h>
#include <mm\oclassdl.h>
#include <mm\server.h>
#include <mm\address.h>
#include <mm\server2.h>
#include <mm\memfree.h>
#include <mmreg\regutil.h>
#include <mmreg\regread.h>
#include <mmreg\regsave.h>
#include <dhcpapi.h>
//================================================================================
// THE FOLLOWING FUNCTIONS HAVE BEEN COPIED OVER FROM RPCAPI1.C (IN THE
// DHCP\SERVER\SERVER DIRECTORY).
//================================================================================
#undef DhcpPrint
#define DhcpPrint(X)
#define DhcpAssert(X)
typedef struct _OPTION_BIN { DWORD DataSize; DHCP_OPTION_DATA_TYPE OptionType; DWORD NumElements; BYTE Data[0]; } OPTION_BIN, *LPOPTION_BIN;
#define IS_SPACE_AVAILABLE(FilledSize, AvailableSize, RequiredSpace ) ((FilledSize) + (RequiredSpace) <= (AvailableSize) )
BOOL _inline CheckForVendor( IN DWORD OptId, IN BOOL IsVendor ) { if( IsVendor ) return (256 <= OptId); return 256 > OptId; }
DWORD _inline ConvertOptIdToRPCValue( IN DWORD OptId, IN BOOL IsVendorUnused ) { return OptId % 256; }
DWORD _inline ConvertOptIdToMemValue( IN DWORD OptId, IN BOOL IsVendor ) { if( IsVendor ) return OptId + 256; return OptId; }
DWORD DhcpConvertOptionRPCToRegFormat( IN LPDHCP_OPTION_DATA Option, IN OUT LPBYTE RegBuffer, // OPTIONAL
IN OUT DWORD *BufferSize // input: buffer size, output: filled buffer size
) { OPTION_BIN Dummy; DWORD AvailableSize; DWORD FilledSize; DWORD nElements; DWORD i; DWORD DataLength; DWORD Length; DHCP_OPTION_DATA_TYPE OptType; LPBYTE BufStart;
AvailableSize = *BufferSize; FilledSize = 0; BufStart = RegBuffer;
Dummy.DataSize = sizeof(Dummy); Dummy.OptionType = DhcpByteOption; Dummy.NumElements = 0; FilledSize = ROUND_UP_COUNT(sizeof(Dummy), ALIGN_WORST);
RegBuffer += FilledSize; // will do this actual filling at the very end
if( NULL == Option || 0 == Option->NumElements ) { OptType = DhcpByteOption; nElements =0; } else { OptType = Option->Elements[0].OptionType; nElements = Option->NumElements; }
for( i = 0; i < nElements ; i ++ ) { // marshal each argument in
if( OptType != Option->Elements[i].OptionType ) { return ERROR_INVALID_PARAMETER; // do not allow random option types, all got to be same
}
switch(OptType) { case DhcpByteOption: if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD)) ) { *((LPDWORD)RegBuffer) = Option->Elements[i].Element.ByteOption; RegBuffer += sizeof(DWORD); } FilledSize += sizeof(DWORD); break; case DhcpWordOption: if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD)) ) { *((LPDWORD)RegBuffer) = Option->Elements[i].Element.WordOption; RegBuffer += sizeof(DWORD); } FilledSize += sizeof(DWORD); break; case DhcpDWordOption: if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD) )) { *((LPDWORD)RegBuffer) = Option->Elements[i].Element.DWordOption; RegBuffer += sizeof(DWORD); } FilledSize += sizeof(DWORD); break; case DhcpDWordDWordOption: if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD_DWORD)) ) { *((LPDWORD_DWORD)RegBuffer) = Option->Elements[i].Element.DWordDWordOption; RegBuffer += sizeof(DWORD); } FilledSize += sizeof(DWORD_DWORD); break; case DhcpIpAddressOption: if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DHCP_IP_ADDRESS)) ) { *((LPDHCP_IP_ADDRESS)RegBuffer) = Option->Elements[i].Element.IpAddressOption; RegBuffer += sizeof(DHCP_IP_ADDRESS); } FilledSize += sizeof(DHCP_IP_ADDRESS); break; case DhcpStringDataOption: if( NULL == Option->Elements[i].Element.StringDataOption ) { DataLength = ROUND_UP_COUNT((FilledSize + sizeof(DWORD) + sizeof(WCHAR)), ALIGN_DWORD); DataLength -= FilledSize; if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength ) ) { *(LPDWORD)RegBuffer = (DWORD) sizeof(WCHAR); RegBuffer += sizeof(DWORD); *(LPWSTR)RegBuffer = L'\0'; RegBuffer += ROUND_UP_COUNT(sizeof(WCHAR), ALIGN_DWORD); DhcpAssert(sizeof(DWORD) + ROUND_UP_COUNT(sizeof(WCHAR),ALIGN_DWORD) == DataLength); } FilledSize += DataLength; break; }
Length = (1+wcslen(Option->Elements[i].Element.StringDataOption))*sizeof(WCHAR); DataLength = ROUND_UP_COUNT((Length + FilledSize + sizeof(DWORD)), ALIGN_DWORD); DataLength -= FilledSize;
if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength) ) { *((LPDWORD)RegBuffer) = Length; RegBuffer += sizeof(DWORD); memcpy(RegBuffer, Option->Elements[i].Element.StringDataOption, Length ); RegBuffer += ROUND_UP_COUNT(Length, ALIGN_DWORD); DhcpAssert(ROUND_UP_COUNT(Length,ALIGN_DWORD) + sizeof(DWORD) == DataLength); } FilledSize += DataLength; break; case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: Length = Option->Elements[i].Element.BinaryDataOption.DataLength; DataLength = ROUND_UP_COUNT((FilledSize+Length+sizeof(DWORD)), ALIGN_DWORD); DataLength -= FilledSize; if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength) ) { *((LPDWORD)RegBuffer) = Length; RegBuffer += sizeof(DWORD); memcpy(RegBuffer, Option->Elements[i].Element.BinaryDataOption.Data, Length); Length = ROUND_UP_COUNT(Length, ALIGN_DWORD); DhcpAssert(Length + sizeof(DWORD) == DataLength); RegBuffer += Length; } FilledSize += DataLength; break; default: return ERROR_INVALID_PARAMETER; // Dont support any other kind of options
} } // Length = ROUND_UP_COUNT(FilledSize, ALIGN_WORST);
*BufferSize = FilledSize; if( AvailableSize < FilledSize ) return ERROR_MORE_DATA;
Dummy.NumElements = nElements; Dummy.DataSize = *BufferSize; Dummy.OptionType = OptType; memcpy(BufStart, (LPBYTE)&Dummy, sizeof(Dummy)); return ERROR_SUCCESS; }
//================================================================================
// helper routines for ds..
//================================================================================
VOID static MemFreeFunc( IN OUT LPVOID Memory ) { MemFree(Memory); }
//DOC DhcpConvertOptionRegToRPCFormat2 converts from the registry format option
//DOC to the RPC format. Additionally, it packs the whole stuff in one buffer.
//DOC If the Option buffer size (in bytes) as specified for input, is insufficient
//DOC to hold all the data, then, the function returns ERROR_MORE_DATA and sets
//DOC the same Size parameter to hold the actual # of bytes space required.
//DOC On a successful conversion, Size holds the total # of bytes copied.
//DOC Most of the code is same as for DhcpConvertOptionRegToRPCFormat
//DOC
DWORD DhcpConvertOptionRegToRPCFormat2( // convert from Reg fmt to RPC..
IN LPBYTE Buffer, // reg fmt option buffer
IN DWORD BufferSize, // size of above in bytes
IN OUT LPDHCP_OPTION_DATA Option, // where to fill the option data
IN OUT LPBYTE OptBuf, // buffer for internal option data..
IN OUT DWORD *Size // i/p: sizeof(Option) o/p: reqd size
) { LPOPTION_BIN OptBin; LPBYTE OptData; LPBYTE DataBuffer; DWORD OptSize; DWORD OptType; DWORD nElements; DWORD i; DWORD NetworkULong; DWORD DataLength; DWORD FilledSize; DWORD AvailableSize; WORD NetworkUShort; LPDHCP_OPTION_DATA_ELEMENT Elements;
if( !Buffer || !BufferSize || !Size ) return ERROR_INVALID_PARAMETER; AvailableSize = *Size; FilledSize = *Size = 0;
OptBin = (LPOPTION_BIN)Buffer;
if(OptBin->DataSize != BufferSize) { // internal error!
DhcpPrint((DEBUG_ERRORS, "Internal error while parsing options\n")); DhcpAssert(FALSE); return ERROR_INVALID_PARAMETER; }
OptType = OptBin->OptionType; // copy highly used stuff
nElements = OptBin->NumElements; OptData = OptBin->Data; OptData = ROUND_UP_COUNT(sizeof(OPTION_BIN), ALIGN_WORST) + (LPBYTE)OptBin;
if( Option ) { Option->NumElements = 0; Option->Elements = NULL; }
if( 0 == nElements ) { return ERROR_SUCCESS; }
Elements = (LPVOID)OptBuf; FilledSize += nElements * ROUND_UP_COUNT(sizeof(DHCP_OPTION_DATA_ELEMENT), ALIGN_WORST); if( !IS_SPACE_AVAILABLE(FilledSize, AvailableSize, 0 ) ) { Elements = NULL; // not enough space is really available..
}
for(i = 0; i < nElements ; i ++ ) { // marshal the elements in the data buffer
if( Elements ) { // copy only when space is there
Elements[i].OptionType = OptType; }
switch( OptType ) { // each type has diff fields to look at
case DhcpByteOption: if( Elements ) { Elements[i].Element.ByteOption = *((LPBYTE)OptData); } OptData += sizeof(DWORD); break; case DhcpWordOption: if( Elements ) { Elements[i].Element.WordOption = (WORD)(*((LPDWORD)OptData)); } OptData += sizeof(DWORD); break; case DhcpDWordOption: if( Elements ) { Elements[i].Element.DWordOption = *((LPDWORD)OptData); } OptData += sizeof(DWORD); break; case DhcpDWordDWordOption: if( Elements ) { Elements[i].Element.DWordDWordOption = *((LPDWORD_DWORD)OptData); } OptData += sizeof(DWORD_DWORD); break; case DhcpIpAddressOption: if( Elements ) { Elements[i].Element.IpAddressOption = *((LPDHCP_IP_ADDRESS)OptData); } OptData += sizeof(DHCP_IP_ADDRESS); break; case DhcpStringDataOption: case DhcpBinaryDataOption: case DhcpEncapsulatedDataOption: DataLength = *((LPWORD)OptData); OptData += sizeof(DWORD);
if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength) ) { DataBuffer = (LPVOID)(FilledSize + OptBuf); } else { DataBuffer = NULL; }
FilledSize += DataLength;
if( DataBuffer ) { RtlCopyMemory( DataBuffer, OptData, DataLength ); } OptData += ROUND_UP_COUNT(DataLength, ALIGN_DWORD);
if( Elements ) { if( OptType == DhcpStringDataOption ) { Elements[i].Element.StringDataOption = (LPWSTR)DataBuffer; } else { Elements[i].Element.BinaryDataOption.DataLength = DataLength; Elements[i].Element.BinaryDataOption.Data = DataBuffer; } }
DhcpAssert( i == 0 ); // should not be more than one binary element specified
if( i > 0 ) { DhcpPrint(( DEBUG_OPTIONS, "Multiple Binary option packed\n")); } break; default: DhcpPrint(( DEBUG_OPTIONS, "Unknown option found\n")); break; } }
if( Option ) { Option->NumElements = i; // nElements maybe?
Option->Elements = Elements; }
*Size = FilledSize;
if( FilledSize <= AvailableSize ) return ERROR_SUCCESS; return ERROR_MORE_DATA; // did not copy everything actually.
}
//================================================================================
// DS Access Routines
//================================================================================
//BeginExport(function)
//DOC DhcpDsCreateOptionDef tries to create an option definition in the DS with the
//DOC given attributes. The option must not exist in the DS prior to this call.
//DOC There are requirements on the fmt used in the DS.
DWORD DhcpDsCreateOptionDef( // create option definition
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR Name, // option name
IN LPWSTR Comment, // OPTIONAL option comment
IN LPWSTR ClassName, // OPTIONAL unused, opt class
IN DWORD OptId, // # between 0-255 per DHCP draft
IN DWORD OptType, // some option flags
IN LPBYTE OptVal, // default option value
IN DWORD OptLen // # of bytes of above
) //EndExport(function)
{ DWORD Result, unused; ARRAY OptDefAttribs; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; ARRAY_LOCATION Loc;
MemArrayInit(&OptDefAttribs); Result = DhcpDsGetLists( // get list of opt defs frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
Result = MemArrayNextLoc(&OptDefAttribs, &Loc) ) { Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) { if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // mismatch
}
if( ClassName ) { // need to check class name
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ThisAttrib->String3, ClassName) ) continue; }
Result = ERROR_DDS_OPTION_ALREADY_EXISTS; goto Cleanup; } }
NothingPresent(&DummyAttrib); // prepare an elt to add to list
STRING1_PRESENT(&DummyAttrib); if( Comment ) STRING2_PRESENT(&DummyAttrib); if( ClassName ) STRING3_PRESENT(&DummyAttrib); DWORD1_PRESENT(&DummyAttrib); BINARY1_PRESENT(&DummyAttrib); FLAGS1_PRESENT(&DummyAttrib);
DummyAttrib.String1 = Name; // fill in reqd fields only
if( Comment ) DummyAttrib.String2 = Comment; if( ClassName ) DummyAttrib.String3 = ClassName; DummyAttrib.Dword1 = OptId; DummyAttrib.Flags1 = OptType; DummyAttrib.Binary1 = OptVal; DummyAttrib.BinLen1 = OptLen;
Result = MemArrayAddElement(&OptDefAttribs, &DummyAttrib); if( ERROR_SUCCESS != Result ) goto Cleanup; // Add dummy element to list
Result = DhcpDsSetLists( // set the new list in DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* SetParams */ &unused, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti.. */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* ClassDescriptio.. */ NULL, /* Classes */ NULL );
(void)MemArrayLastLoc(&OptDefAttribs, &Loc); // clear up list to way it was
//- ERROR_SUCCESS == Result
(void)MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && ThisAttrib == &DummyAttrib
Cleanup: // free up any memory used
(void)MemArrayFree(&OptDefAttribs, MemFreeFunc); return Result; }
//BeginExport(function)
//DOC DhcpDsModifyOptionDef tries to modify an existing optdef in the DS with the
//DOC given attributes. The option must exist in the DS prior to this call.
//DOC There are requirements on the fmt used in the DS.
DWORD DhcpDsModifyOptionDef( // modify option definition
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR Name, // option name
IN LPWSTR Comment, // OPTIONAL option comment
IN LPWSTR ClassName, // OPTIONAL unused, opt class
IN DWORD OptId, // # between 0-255 per DHCP draft
IN DWORD OptType, // some option flags
IN LPBYTE OptVal, // default option value
IN DWORD OptLen // # of bytes of above
) //EndExport(function)
{ DWORD Result, unused; ARRAY OptDefAttribs; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; ARRAY_LOCATION Loc;
MemArrayInit(&OptDefAttribs); Result = DhcpDsGetLists( // get list of opt defs frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
Result = MemArrayNextLoc(&OptDefAttribs, &Loc) ) { Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) { if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // mismatch
}
if( ClassName ) { // need to check class name
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ThisAttrib->String3, ClassName) ) continue; }
Result = MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result
MemFreeFunc(ThisAttrib); Result = ERROR_SUCCESS; break; } }
if( ERROR_SUCCESS != Result ) { // option def was not found
Result = ERROR_DDS_OPTION_DOES_NOT_EXIST; }
NothingPresent(&DummyAttrib); // prepare an elt to add to list
STRING1_PRESENT(&DummyAttrib); if( Comment ) STRING2_PRESENT(&DummyAttrib); if( ClassName ) STRING3_PRESENT(&DummyAttrib); DWORD1_PRESENT(&DummyAttrib); BINARY1_PRESENT(&DummyAttrib); FLAGS1_PRESENT(&DummyAttrib);
DummyAttrib.String1 = Name; // fill in reqd fields only
if( Comment ) DummyAttrib.String2 = Comment; if( ClassName )DummyAttrib.String3 = ClassName; DummyAttrib.Dword1 = OptId; DummyAttrib.Flags1 = OptType; DummyAttrib.Binary1 = OptVal; DummyAttrib.BinLen1 = OptLen;
Result = MemArrayAddElement(&OptDefAttribs, &DummyAttrib); if( ERROR_SUCCESS != Result ) goto Cleanup; // Add dummy element to list
Result = DhcpDsSetLists( // set the new list in DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* SetParams */ &unused, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti.. */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* ClassDescriptio.. */ NULL, /* Classes */ NULL );
(void)MemArrayLastLoc(&OptDefAttribs, &Loc); // clear up list to way it was
//- ERROR_SUCCESS == Result
(void)MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && ThisAttrib == &DummyAttrib
Cleanup: // free up any memory used
(void)MemArrayFree(&OptDefAttribs, MemFreeFunc); return Result; }
//BeginExport(function)
//DOC DhcpDsEnumOptionDefs gets the list of options defined for the given class.
//DOC Currently, class is ignored as option defs dont have classes associated.
//DOC There are requirements on the fmt used in the DS.
DWORD DhcpDsEnumOptionDefs( // enum list of opt defs in DS
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // OPTIONAL, unused.
IN BOOL IsVendor, // vendor only? non-vendor only?
OUT LPDHCP_OPTION_ARRAY *RetOptArray // allocated and fill this.
) //EndExport(function)
{ DWORD Result, Result2, unused, Size, Size2, i, AllocSize; ARRAY OptDefAttribs; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; ARRAY_LOCATION Loc; LPDHCP_OPTION_ARRAY OptArray; LPBYTE Ptr;
*RetOptArray = NULL; MemArrayInit(&OptDefAttribs); Result = DhcpDsGetLists( // get list of opt defs frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
Size = i = 0; // calculate size
Size += ROUND_UP_COUNT(sizeof(DHCP_OPTION_ARRAY), ALIGN_WORST);
for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
Result = MemArrayNextLoc(&OptDefAttribs, &Loc) ) { Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
continue; // skip it
}
if( !CheckForVendor(ThisAttrib->Dword1, IsVendor) ) { continue; // separate vendor and non-vendor
}
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; }
Size2 = 0; Result2 = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ NULL, // will allocate this later
/* OptBuf */ NULL, /* Size */ &Size2 ); if( ERROR_MORE_DATA == Result2 ) Result2 = ERROR_SUCCESS; if( ERROR_SUCCESS != Result2 ) continue; // errors? skip this attrib
Size += ROUND_UP_COUNT(Size2, ALIGN_WORST); Size2 = sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1)); if( IS_STRING2_PRESENT(ThisAttrib) ) { // if comment is present..
Size2 += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String2)); } Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
i ++; }
Size += ROUND_UP_COUNT(i* sizeof(DHCP_OPTION), ALIGN_WORST);
Ptr = MemAlloc(AllocSize = Size); OptArray = (LPVOID)Ptr; if( NULL == OptArray ) return ERROR_NOT_ENOUGH_MEMORY;
Size = 0; // this time, fill in the values
Size += ROUND_UP_COUNT(sizeof(DHCP_OPTION_ARRAY), ALIGN_WORST); Ptr += Size; OptArray->NumElements = i; OptArray->Options = (LPVOID)Ptr; Size += ROUND_UP_COUNT(i* sizeof(DHCP_OPTION), ALIGN_WORST); Ptr += ROUND_UP_COUNT(i* sizeof(DHCP_OPTION), ALIGN_WORST);
i = 0; for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
Result = MemArrayNextLoc(&OptDefAttribs, &Loc) ) { Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
continue; // skip it
}
if( !CheckForVendor(ThisAttrib->Dword1, IsVendor) ) { continue; // separate vendor and non-vendor
}
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; }
Size2 = AllocSize - Size; Result2 = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ &OptArray->Options[i].DefaultValue, /* OptBuf */ Ptr, /* Size */ &Size2 ); //- ERROR_MORE_DATA != Result2
if( ERROR_SUCCESS != Result2 ) continue; // errors? skip this attrib
Size += ROUND_UP_COUNT(Size2, ALIGN_WORST); Ptr += ROUND_UP_COUNT(Size2, ALIGN_WORST);
OptArray->Options[i].OptionID = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE); if( IS_FLAGS1_PRESENT(ThisAttrib) ) { // if some flags present
OptArray->Options[i].OptionType = ThisAttrib->Flags1; } else { // if no flags present, assume 0 type
OptArray->Options[i].OptionType = 0; }
OptArray->Options[i].OptionName = (LPVOID)Ptr; wcscpy((LPWSTR)Ptr, ThisAttrib->String1); Ptr += sizeof(WCHAR)*(1+wcslen((LPWSTR)Ptr));
Size2 = sizeof(WCHAR)*(1+wcslen(ThisAttrib->String1)); if( IS_STRING2_PRESENT(ThisAttrib) ) { // if comment is present..
Size2 += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String2)); OptArray->Options[i].OptionComment = (LPVOID)Ptr; wcscpy((LPWSTR)Ptr, ThisAttrib->String2); } else { OptArray->Options[i].OptionComment = NULL; }
Size += ROUND_UP_COUNT(Size2, ALIGN_WORST); Ptr = ROUND_UP_COUNT(Size2, ALIGN_WORST) + (LPBYTE)(OptArray->Options[i].OptionName);
i ++; }
//- OptArray->NumElements == i
*RetOptArray = OptArray; return ERROR_SUCCESS; }
//BeginExport(function)
//DOC DhcpDsDeleteOptionDef deletes an option definition in the DS based on the option id.
//DOC Note that the ClassName field is currently ignored.
//DOC No error is reported if the option is not present in the DS.
//DOC
DWORD DhcpDsDeleteOptionDef( // enum list of opt defs in DS
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // OPTIONAL, unused.
IN DWORD OptId ) //EndExport(function)
{ DWORD Result, Result2, unused; ARRAY OptDefAttribs; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; ARRAY_LOCATION Loc;
MemArrayInit(&OptDefAttribs); Result = DhcpDsGetLists( // get list of opt defs frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
Result = MemArrayNextLoc(&OptDefAttribs, &Loc) ) { Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) { if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; }
Result = MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result
MemFreeFunc(ThisAttrib); Result = ERROR_SUCCESS; break; } }
if( ERROR_SUCCESS != Result ) { // could not find the option in DS
Result = ERROR_SUCCESS; // pretend everything was fine
} else { Result = DhcpDsSetLists( // set the new list in DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* SetParams */ &unused, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti.. */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* ClassDescriptio.. */ NULL, /* Classes */ NULL ); }
(void) MemArrayFree(&OptDefAttribs, MemFreeFunc);
return Result; }
//BeginExport(function)
//DOC DhcpDsDeleteOptionDef deletes an option definition in the DS based on the option id.
//DOC Note that the ClassName field is currently ignored.
//DOC No error is reported if the option is not present in the DS.
//DOC
DWORD DhcpDsGetOptionDef( // enum list of opt defs in DS
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // OPTIONAL, unused.
IN DWORD OptId, OUT LPDHCP_OPTION *OptInfo ) //EndExport(function)
{ DWORD Result, Result2, unused; ARRAY OptDefAttribs; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; ARRAY_LOCATION Loc;
MemArrayInit(&OptDefAttribs); Result = DhcpDsGetLists( // get list of opt defs frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
Result = MemArrayNextLoc(&OptDefAttribs, &Loc) ) { Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { // invalid attributes?
continue; }
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) { if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; }
Result = ERROR_SUCCESS; break; } }
if( ERROR_SUCCESS == Result ) do { ULONG Size, Size2; LPBYTE Ptr;
Size2 = Size = 0; Result = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ NULL, // will allocate this later
/* OptBuf */ NULL, /* Size */ &Size2 ); if( ERROR_MORE_DATA == Result ) Result = ERROR_SUCCESS; if( ERROR_SUCCESS != Result ) break; // errors? skip this attrib
Size = ROUND_UP_COUNT(sizeof(DHCP_OPTION), ALIGN_WORST); Size += ROUND_UP_COUNT(Size2, ALIGN_WORST); Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1)); if( IS_STRING2_PRESENT(ThisAttrib) ) { Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String2)); }
(*OptInfo) = (LPVOID)Ptr = MemAlloc(Size); if( NULL == *OptInfo ) { Result = ERROR_NOT_ENOUGH_MEMORY ; break; } Ptr += ROUND_UP_COUNT(sizeof(DHCP_OPTION), ALIGN_WORST); (*OptInfo)->OptionID = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE); if( IS_FLAGS1_PRESENT(ThisAttrib) ) (*OptInfo)->OptionType = ThisAttrib->Flags1; else (*OptInfo)->OptionType = 0;
Size2 = Size - ROUND_UP_COUNT(sizeof(DHCP_OPTION), ALIGN_WORST); Result = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ &((*OptInfo)->DefaultValue), /* OptBuf */ Ptr, /* Size */ &Size2 ); Ptr += Size2; (*OptInfo)->OptionName = (LPVOID)Ptr; wcscpy((LPWSTR)Ptr, ThisAttrib->String1); if( !IS_STRING2_PRESENT(ThisAttrib) ) (*OptInfo)->OptionComment = NULL; else { Ptr += sizeof(WCHAR)*(1+ wcslen(ThisAttrib->String1)); (*OptInfo)->OptionComment = (LPVOID)Ptr; wcscpy((LPWSTR)Ptr, ThisAttrib->String2); }
Result = ERROR_SUCCESS; } while(0);
(void) MemArrayFree(&OptDefAttribs, MemFreeFunc);
return Result; }
//BeginExport(function)
//DOC DhcpDsSetOptionValue sets the required option value in the DS.
//DOC Note that if the option existed earlier, it is overwritten. Also, the
//DOC option definition is not checked against -- so there need not be an
//DOC option type specified.
//DOC Also, this function works assuming that the option has to be written
//DOC to the current object in DS as given by hObject ptr.
//DOC There are requirements on the fmt used in the DS.
DWORD DhcpDsSetOptionValue( // set option value
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // name of class for this opt
IN LPWSTR UserClass, // name of user class for this opt
IN DWORD OptId, // option id
IN LPDHCP_OPTION_DATA OptData // what is the option
) //EndExport(function)
{ DWORD Result, Result2, unused, ValueSize; ARRAY OptAttribs; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; ARRAY_LOCATION Loc; LPBYTE Value;
MemArrayInit(&OptAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hObject, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ &OptAttribs, /* Classes */ NULL ); // if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&OptAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for option w/ <OptId>
Result = MemArrayNextLoc(&OptAttribs, &Loc) ) { Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) { continue; // user class mismatch
}
if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) { if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; } if( UserClass ) { // need to 've matchin user class
if( !IS_STRING4_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue; }
Result = MemArrayDelElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result
MemFreeFunc(ThisAttrib); break; } }
NothingPresent(&DummyAttrib); // prepare an elt to add to list
// STRING1_PRESENT(&DummyAttrib); // No name or comment
// if( Comment ) STRING2_PRESENT(&DummyAttrib);
if( ClassName ) STRING3_PRESENT(&DummyAttrib);// class name?
if( UserClass ) STRING4_PRESENT(&DummyAttrib);// user class?
DWORD1_PRESENT(&DummyAttrib); // this is option id
BINARY1_PRESENT(&DummyAttrib); // value is this
// FLAGS1_PRESENT(&DummyAttrib); // flags are not currently used
Value = NULL; ValueSize = 0; // dont know the size, find out
Result = DhcpConvertOptionRPCToRegFormat( // first convert to Reg fmt
OptData, NULL, &ValueSize ); if( ERROR_MORE_DATA != Result ) { // oops unexpected turn of evts
Result = ERROR_DDS_UNEXPECTED_ERROR; goto Cleanup; } Value = MemAlloc(ValueSize); // got the size, allocate the mem
if( NULL == Value ) { // this shouldnt happen actually
Result = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } Result = DhcpConvertOptionRPCToRegFormat( // now convert to Reg fmt
OptData, Value, &ValueSize ); if( ERROR_SUCCESS != Result ) { // this should not happen either
return ERROR_DDS_UNEXPECTED_ERROR; }
DummyAttrib.Dword1 = OptId; // option Id
DummyAttrib.String3 = ClassName; // class Name
DummyAttrib.String4 = UserClass; // user class
DummyAttrib.Binary1 = Value; DummyAttrib.BinLen1 = ValueSize;
Result = MemArrayAddElement(&OptAttribs, &DummyAttrib); if( ERROR_SUCCESS != Result ) goto Cleanup; // Add dummy element to list
Result = DhcpDsSetLists( // set the new list in DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hObject, /* SetParams */ &unused, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti.. */ NULL, /* OptionsLocation */ NULL, /* Options */ &OptAttribs, /* ClassDescriptio.. */ NULL, /* Classes */ NULL );
(void)MemArrayLastLoc(&OptAttribs, &Loc); // clear up list to way it was
//- ERROR_SUCCESS == Result
(void)MemArrayDelElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && ThisAttrib == &DummyAttrib
Cleanup: // free up any memory used
(void)MemArrayFree(&OptAttribs, MemFreeFunc); if( Value ) MemFree(Value); return Result; }
//BeginExport(function)
//DOC DhcpDsRemoveOptionValue deletes the required option value from DS
//DOC the specific option value should exist in DS, else error.
//DOC Also, this function works assuming that the option has been written
//DOC to the current object in DS as given by hObject ptr.
//DOC There are requirements on the fmt used in the DS.
DWORD DhcpDsRemoveOptionValue( // remove option value
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // name of class for this opt
IN LPWSTR UserClass, // user class for opt
IN DWORD OptId // option id
) //EndExport(function)
{ DWORD Result, Result2, unused, ValueSize; ARRAY OptAttribs; PEATTRIB ThisAttrib; ARRAY_LOCATION Loc;
MemArrayInit(&OptAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hObject, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ &OptAttribs, /* Classes */ NULL ); // if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&OptAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for option w/ <OptId>
Result = MemArrayNextLoc(&OptAttribs, &Loc) ) { Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) { continue; // user class mismatch
}
if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) { if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; } if( UserClass ) { // need to 've matchin user class
if( !IS_STRING4_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue; }
Result = ERROR_SUCCESS; break; } }
if( ERROR_SUCCESS != Result ) { // option was not present in DS
return ERROR_DDS_OPTION_DOES_NOT_EXIST; }
Result = MemArrayDelElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result
MemFreeFunc(ThisAttrib);
Result = DhcpDsSetLists( // set the new list in DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hObject, /* SetParams */ &unused, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti.. */ NULL, /* OptionsLocation */ NULL, /* Options */ &OptAttribs, /* ClassDescriptio.. */ NULL, /* Classes */ NULL );
(void)MemArrayFree(&OptAttribs, MemFreeFunc); return Result; }
//BeginExport(function)
//DOC DhcpDsGetOptionValue retrieves the particular option value in question.
//DOC This function returns ERROR_DDS_OPTION_DOES_NOT_EXIST if the option was
//DOC not found.
DWORD DhcpDsGetOptionValue( // get option value frm DS
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // name of class for this opt
IN LPWSTR UserClass, // user class this opt belongs 2
IN DWORD OptId, // option id
OUT LPDHCP_OPTION_VALUE *OptionValue // allocate and fill this ptr
) //EndExport(function)
{ DWORD Result, Result2, unused, Size, Size2; ARRAY OptAttribs; PEATTRIB ThisAttrib; ARRAY_LOCATION Loc; LPDHCP_OPTION_VALUE LocalOptionValue;
*OptionValue = NULL; LocalOptionValue = NULL; MemArrayInit(&OptAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hObject, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ &OptAttribs, /* Classes */ NULL ); // if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&OptAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for option w/ <OptId>
Result = MemArrayNextLoc(&OptAttribs, &Loc) ) { Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) { continue; // user class mismatch
}
if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) { if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; } if( UserClass ) { // need to 've matchin user class
if( !IS_STRING4_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue; }
Result = ERROR_SUCCESS; break; }
Result = ERROR_SUCCESS; // perfect match
break; }
if( ERROR_SUCCESS != Result ) { // option was not present in DS
return ERROR_DDS_OPTION_DOES_NOT_EXIST; }
Size2 = 0; // calculate the size reqd for mem
Size = ROUND_UP_COUNT(sizeof(*LocalOptionValue), ALIGN_WORST); Result = DhcpConvertOptionRegToRPCFormat2( // convert from RPC to registry fmt
/* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ NULL, /* OptBuf */ NULL, /* Size */ &Size2 // just calculate the size..
); if( ERROR_MORE_DATA != Result ) { // cant really go wrong
Result = ERROR_DDS_UNEXPECTED_ERROR; goto Cleanup; }
LocalOptionValue = MemAlloc(Size); if( NULL == LocalOptionValue ) { Result = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
LocalOptionValue->OptionID = ConvertOptIdToRPCValue(OptId, TRUE); Size2 = Size - ROUND_UP_COUNT(sizeof(*LocalOptionValue), ALIGN_WORST); Result = DhcpConvertOptionRegToRPCFormat2( // convert from RPC to registry fmt
/* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ &LocalOptionValue->Value, /* OptBuf */ ROUND_UP_COUNT(sizeof(*LocalOptionValue), ALIGN_WORST) + (LPBYTE)LocalOptionValue, /* Size */ &Size2 // just calculate the size..
); if( ERROR_SUCCESS != Result ) { // cant really go wrong
if( ERROR_MORE_DATA == Result ) { // this can cause confusion..
Result = ERROR_DDS_UNEXPECTED_ERROR; } goto Cleanup; }
*OptionValue = LocalOptionValue;
Cleanup:
if( ERROR_SUCCESS != Result ) { if( LocalOptionValue ) MemFreeFunc(LocalOptionValue); *OptionValue = NULL; }
(void)MemArrayFree(&OptAttribs, MemFreeFunc); return Result;
}
//BeginExport(function)
//DOC DhcpDsEnumOptionValues enumerates the list of options for a given class
//DOC Also, depending on whether IsVendor is TRUE or false, this function enumerates
//DOC only vendor specific or only non-vendor-specific options respectively.
//DOC This function gets the whole bunch in one shot.
DWORD DhcpDsEnumOptionValues( // get option values from DS
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // name of class for this opt
IN LPWSTR UserClass, // for which user class?
IN DWORD IsVendor, // enum only vendor/non-vendor?
OUT LPDHCP_OPTION_VALUE_ARRAY *OptionValues // allocate option values..
) //EndExport(function)
{ DWORD Result, Result2, unused, Size, Size2, i; DWORD AllocSize; ARRAY OptAttribs; PEATTRIB ThisAttrib; ARRAY_LOCATION Loc; LPDHCP_OPTION_VALUE_ARRAY LocalOptionValueArray; LPBYTE Ptr;
*OptionValues = NULL; LocalOptionValueArray = NULL; MemArrayInit(&OptAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hObject, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ &OptAttribs, /* Classes */ NULL ); // if( ERROR_SUCCESS != Result ) return Result;
Size = i = 0; for( Result = MemArrayInitLoc(&OptAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // go thru each option, calc size
Result = MemArrayNextLoc(&OptAttribs, &Loc) ) { Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_DWORD1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // illegal attrib, or not this opt
}
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) { continue; // user class mismatch
}
if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; } if( UserClass ) { // need to 've matchin user class
if( !IS_STRING4_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue; }
Size2 = 0; // calculate the size reqd for mem
Result2= DhcpConvertOptionRegToRPCFormat2(// convert from RPC to registry fmt
/* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ NULL, /* OptBuf */ NULL, /* Size */ &Size2 // just calculate the size..
); if( ERROR_MORE_DATA != Result2 ) { // cant really go wrong
continue; // skip this attrib in this case
}
Size += ROUND_UP_COUNT(Size2, ALIGN_WORST); i ++; } Size += ROUND_UP_COUNT( i * sizeof(DHCP_OPTION_VALUE), ALIGN_WORST); Size += ROUND_UP_COUNT( sizeof(DHCP_OPTION_VALUE_ARRAY ), ALIGN_WORST);
Ptr = MemAlloc(AllocSize = Size); LocalOptionValueArray = (LPVOID)Ptr; if( NULL == LocalOptionValueArray ) { Result = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
Ptr += ROUND_UP_COUNT( sizeof(DHCP_OPTION_VALUE_ARRAY ), ALIGN_WORST); LocalOptionValueArray->Values = (LPVOID)Ptr; Ptr += ROUND_UP_COUNT( i * sizeof(DHCP_OPTION_VALUE), ALIGN_WORST);
Size = i = 0; for( Result = MemArrayInitLoc(&OptAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // go thru each opt, fill data
Result = MemArrayNextLoc(&OptAttribs, &Loc) ) { Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_DWORD1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // illegal attrib, or not this opt
}
if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) { continue; // classname mismatch
}
if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) { continue; // user class mismatch
}
if( ClassName ) { // need to have matching class
if( !IS_STRING3_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue; } if( UserClass ) { // need to 've matchin user class
if( !IS_STRING4_PRESENT(ThisAttrib) ) continue; if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue; }
Size2 = AllocSize - Size; Result2= DhcpConvertOptionRegToRPCFormat2(// convert from RPC to registry fmt
/* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ &LocalOptionValueArray->Values[i].Value, /* OptBuf */ Ptr, /* Size */ &Size2 // just calculate the size..
); if( ERROR_SUCCESS != Result2 ) { // cant really go wrong
continue; // skip this attrib in this case
}
LocalOptionValueArray->Values[i].OptionID = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE); Size += ROUND_UP_COUNT(Size2, ALIGN_WORST); Ptr += ROUND_UP_COUNT(Size2, ALIGN_WORST);
i ++; }
LocalOptionValueArray->NumElements = i; *OptionValues = LocalOptionValueArray;
Cleanup:
if( ERROR_SUCCESS != Result ) { if( LocalOptionValueArray ) MemFreeFunc(LocalOptionValueArray); *OptionValues = NULL; }
(void)MemArrayFree(&OptAttribs, MemFreeFunc); return Result;
}
//BeginExport(function)
//DOC DhcpDsCreateClass creates a given class in the DS. The class should not
//DOC exist prior to this in the DS (if it does, this fn returns error
//DOC ERROR_DDS_CLASS_EXISTS).
DWORD DhcpDsCreateClass( // create this class in the ds
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // name of class..
IN LPWSTR ClassComment, // comment for this class
IN LPBYTE ClassData, // the bytes that form the class data
IN DWORD ClassDataLen, // # of bytes of above
IN BOOL IsVendor // is this a vendor class?
) //EndExport(function)
{ DWORD Result, Result2, unused; ARRAY ClassAttribs; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib; EATTRIB DummyAttrib;
if( NULL == ClassName || NULL == ClassData || 0 == ClassDataLen ) return ERROR_INVALID_PARAMETER;
MemArrayInit(&ClassAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ &ClassAttribs ); // if( ERROR_SUCCESS != Result ) return Result;
Result = MemArrayInitLoc(&ClassAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { // search for existing class
Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
Result = MemArrayNextLoc(&ClassAttribs, &Loc);
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // invalid attrib for a class
}
if( 0 == wcscmp(ClassName, ThisAttrib->String1) ) { Result = ERROR_DDS_CLASS_EXISTS; // gotcha! same name
goto Cleanup; } }
NothingPresent(&DummyAttrib); // create an attrib for the class
STRING1_PRESENT(&DummyAttrib); // class name
if( ClassComment ) { STRING2_PRESENT(&DummyAttrib); // class comment
} BINARY1_PRESENT(&DummyAttrib); // class data
FLAGS1_PRESENT(&DummyAttrib); // vendorclass etc information
DummyAttrib.String1 = ClassName; // now fill in the actual values
DummyAttrib.String2 = ClassComment; DummyAttrib.Binary1 = ClassData; DummyAttrib.BinLen1 = ClassDataLen; DummyAttrib.Flags1 = IsVendor;
Result = MemArrayAddElement(&ClassAttribs, &DummyAttrib); if( ERROR_SUCCESS != Result ) { // could not add an elt? uh uh.
goto Cleanup; }
Result = DhcpDsSetLists( // write back the modified list
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* SetParams */ &unused, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti.. */ NULL, /* OptionsLocation */ NULL, /* Options */ NULL, /* ClassDescriptio.. */ NULL, /* Classes */ &ClassAttribs );
// now try to remove the dummy element that was added..
Result2 = MemArrayLastLoc(&ClassAttribs, &Loc); //- ERROR_SUCCESS == Result2
Result2 = MemArrayDelElement(&ClassAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result2 && ThisAttrib == &DummyAttrib
Cleanup:
(void) MemArrayFree(&ClassAttribs, MemFreeFunc); return Result; }
//BeginExport(function)
//DOC DhcpDsDeleteClass deletes the class from off the DS, and returns an error
//DOC if the class did not exist in the DS for hte given server object.
DWORD DhcpDsDeleteClass( // delete the class from the ds
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName // name of class..
) //EndExport(function)
{ DWORD Result, Result2, unused; ARRAY ClassAttribs; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib; EATTRIB DummyAttrib;
if( NULL == ClassName ) return ERROR_INVALID_PARAMETER;
MemArrayInit(&ClassAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ &ClassAttribs ); // if( ERROR_SUCCESS != Result ) return Result;
for( Result = MemArrayInitLoc(&ClassAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for existing class
Result = MemArrayNextLoc(&ClassAttribs, &Loc) ) { Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // invalid attrib for a class
}
if( 0 == wcscmp(ClassName, ThisAttrib->String1) ) { Result = ERROR_SUCCESS; // gotcha! same name
break; }
}
if( ERROR_SUCCESS != Result ) { Result = ERROR_DDS_CLASS_DOES_NOT_EXIST; goto Cleanup; }
Result = MemArrayDelElement(&ClassAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
MemFreeFunc(ThisAttrib);
Result = DhcpDsSetLists( // write back the modified list
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* SetParams */ &unused, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti.. */ NULL, /* OptionsLocation */ NULL, /* Options */ NULL, /* ClassDescriptio.. */ NULL, /* Classes */ &ClassAttribs );
Cleanup: (void) MemArrayFree(&ClassAttribs, MemFreeFunc); return Result; }
//BeginExport(function)
//DOC this is not yet implemented.
DWORD DhcpDsModifyClass( // modify a class in the DS
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // name of class -- this is the key
IN LPWSTR ClassComment, // comment for this class
IN LPBYTE ClassData, // the bytes that form the class data
IN DWORD ClassDataLen // # of bytes of above
) //EndExport(function)
{ return ERROR_CALL_NOT_IMPLEMENTED; }
//BeginExport(function)
//DOC DhcpDsGetClassInfo get information on a class by doing a search based
//DOC on either the class name or the class data fields. ClassName is guaranteed
//DOC to be unique. ClassData may/maynot be unique. The search is done in the DS,
//DOC so things are likely to be a lot slower than they should be.
//DOC This should be fixed by doing some intelligent searches.
//DOC Note that the hServer and the hDhcpC handles should point to the right objects.
//DOC
DWORD DhcpDsGetClassInfo( // get class details for given class
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
IN LPWSTR ClassName, // OPTIONAL search on class name
IN LPBYTE ClassData, // OPTIONAL srch on class data
IN DWORD ClassDataLen, // # of bytes of ClassData
OUT LPDHCP_CLASS_INFO *ClassInfo // allocate and copy ptr
) //EndExport(function)
{ DWORD Result, Result2, Size; DWORD IsVendor, Flags; ARRAY ClassAttribs; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; LPDHCP_CLASS_INFO LocalClassInfo; LPBYTE Ptr; LPWSTR ClassComment;
if( NULL == ClassName || NULL == ClassData || 0 == ClassDataLen ) return ERROR_INVALID_PARAMETER;
LocalClassInfo = *ClassInfo = NULL; MemArrayInit(&ClassAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ &ClassAttribs ); // if( ERROR_SUCCESS != Result ) return Result;
Result = MemArrayInitLoc(&ClassAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { // search for existing class
Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
Result = MemArrayNextLoc(&ClassAttribs, &Loc);
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // invalid attrib for a class
}
if( 0 == ThisAttrib->BinLen1 ) { // invalid attrib for this class
continue; }
if( ClassName ) { // if srching on ClassName field
if( 0 == wcscmp(ClassName, ThisAttrib->String1) ) { Result = ERROR_SUCCESS; // gotcha! same name
break; } } else { // srching on ClassData field
if( ClassDataLen != ThisAttrib->BinLen1 ) continue; // nope mismatch
if( 0 == memcpy(ClassData, ThisAttrib->Binary1, ClassDataLen) ) { Result = ERROR_SUCCESS; // gotcha! matching bits
break; } } }
if( ERROR_SUCCESS != Result ) { // did not find the class
Result = ERROR_DDS_CLASS_DOES_NOT_EXIST; goto Cleanup; }
ClassName = ThisAttrib->String1; if( IS_STRING2_PRESENT(ThisAttrib) ) { ClassComment = ThisAttrib->String2; } else { ClassComment = NULL; } ClassData = ThisAttrib->Binary1; ClassDataLen = ThisAttrib->BinLen1; if( IS_FLAGS1_PRESENT(ThisAttrib) ) { IsVendor = ThisAttrib->Flags1; } else IsVendor = 0; if( IS_FLAGS2_PRESENT(ThisAttrib) ) { Flags = ThisAttrib->Flags2; } else Flags = 0;
Size = 0; // calculate size reqd
Size = ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO),ALIGN_WORST); Size += sizeof(WCHAR)*(wcslen(ClassName)+1); // alloc space for name
if( ClassComment ) { // alloc space for comment
Size += sizeof(WCHAR)*(wcslen(ClassComment) +1); } Size += ThisAttrib->BinLen1; // alloc space for data
Ptr = MemAlloc(Size); // allocate memory
LocalClassInfo = (LPVOID)Ptr; if( NULL == LocalClassInfo ) { Result = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
Size = 0; // copy the stuff in
Size = ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO),ALIGN_WORST);
LocalClassInfo->ClassName = (LPVOID)(Size + Ptr); wcscpy(LocalClassInfo->ClassName, ClassName); Size += sizeof(WCHAR)*(wcslen(ClassName)+1); if( NULL == ClassComment ) { LocalClassInfo->ClassComment = NULL; } else { LocalClassInfo->ClassComment = (LPVOID)(Size + Ptr); wcscpy(LocalClassInfo->ClassComment, ThisAttrib->String2 ); Size += sizeof(WCHAR)*(wcslen(ThisAttrib->String2) +1); } LocalClassInfo->ClassDataLength = ThisAttrib->BinLen1; LocalClassInfo->ClassData = Size+Ptr; memcpy(LocalClassInfo->ClassData, ThisAttrib->Binary1, ThisAttrib->BinLen1); LocalClassInfo->IsVendor = IsVendor; LocalClassInfo->Flags = Flags;
*ClassInfo = LocalClassInfo; Result = ERROR_SUCCESS;
Cleanup:
(void) MemArrayFree(&ClassAttribs, MemFreeFunc); return Result; }
//BeginExport(function)
//DOC DhcpDsEnumClasses enumerates the classes for a given server (as specified
//DOC via the hServer object.)
//DOC The memory for Classes is allocated by this function.
DWORD DhcpDsEnumClasses( // get the list of classes frm ds
IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
IN DWORD Reserved, // must be zero, future use
OUT LPDHCP_CLASS_INFO_ARRAY *Classes // allocate memory for this
) //EndExport(function)
{ DWORD Result, Result2, Size, Size2, i; DWORD ClassDataLen, IsVendor, Flags; ARRAY ClassAttribs; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; LPDHCP_CLASS_INFO_ARRAY LocalClassInfoArray; LPBYTE Ptr, ClassData; LPWSTR ClassName, ClassComment;
LocalClassInfoArray = *Classes = NULL; MemArrayInit(&ClassAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ &ClassAttribs ); // if( ERROR_SUCCESS != Result ) return Result;
Result = MemArrayInitLoc(&ClassAttribs, &Loc); for(Size = i = 0 // search for existing classes
; ERROR_FILE_NOT_FOUND != Result; Result = MemArrayNextLoc(&ClassAttribs, &Loc) ) { Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // invalid attrib for a class
}
if( 0 == ThisAttrib->BinLen1 ) { // invalid attrib for this class
continue; }
ClassName = ThisAttrib->String1; if( IS_STRING2_PRESENT(ThisAttrib) ) { ClassComment = ThisAttrib->String2; } else { ClassComment = NULL; } ClassData = ThisAttrib->Binary1; ClassDataLen = ThisAttrib->BinLen1;
Size += sizeof(WCHAR)*(wcslen(ClassName)+1); if( ClassComment ) { // alloc space for comment
Size += sizeof(WCHAR)*(wcslen(ClassComment) +1); } Size += ROUND_UP_COUNT(ClassDataLen,ALIGN_WORST);
i ++; }
Size += ROUND_UP_COUNT(i*sizeof(DHCP_CLASS_INFO), ALIGN_WORST); Size += ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO_ARRAY), ALIGN_WORST);
Ptr = MemAlloc(Size); // allocate memory
LocalClassInfoArray = (LPVOID)Ptr; if( NULL == LocalClassInfoArray ) { Result = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
Size = 0; // copy the stuff in
LocalClassInfoArray->NumElements = i; Size += ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO_ARRAY), ALIGN_WORST); LocalClassInfoArray->Classes = (LPVOID) (Size + Ptr); Size += ROUND_UP_COUNT(i*sizeof(DHCP_CLASS_INFO), ALIGN_WORST);
Result = MemArrayInitLoc(&ClassAttribs, &Loc); for(i = 0 // fill in the array with details
; ERROR_FILE_NOT_FOUND != Result; Result = MemArrayNextLoc(&ClassAttribs, &Loc) ) { Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // invalid attrib for a class
}
if( 0 == ThisAttrib->BinLen1 ) { // invalid attrib for this class
continue; }
ClassName = ThisAttrib->String1; if( IS_STRING2_PRESENT(ThisAttrib) ) { ClassComment = ThisAttrib->String2; } else { ClassComment = NULL; } ClassData = ThisAttrib->Binary1; ClassDataLen = ThisAttrib->BinLen1;
LocalClassInfoArray->Classes[i].ClassName = (LPVOID)(Size + Ptr); wcscpy(LocalClassInfoArray->Classes[i].ClassName, ClassName); Size += sizeof(WCHAR)*(wcslen(ClassName)+1); if( NULL == ClassComment ) { LocalClassInfoArray->Classes[i].ClassComment = NULL; } else { LocalClassInfoArray->Classes[i].ClassComment = (LPVOID)(Size + Ptr); wcscpy(LocalClassInfoArray->Classes[i].ClassComment, ThisAttrib->String2 ); Size += sizeof(WCHAR)*(wcslen(ClassComment) +1); } LocalClassInfoArray->Classes[i].ClassDataLength = ClassDataLen; LocalClassInfoArray->Classes[i].ClassData = Size+Ptr; memcpy(LocalClassInfoArray->Classes[i].ClassData, ClassData,ClassDataLen); Size += ROUND_UP_COUNT(ClassDataLen,ALIGN_WORST);
if( IS_FLAGS1_PRESENT(ThisAttrib) ) { IsVendor = ThisAttrib->Flags1; } else IsVendor = 0; if( IS_FLAGS2_PRESENT(ThisAttrib) ) { Flags = ThisAttrib->Flags2; } else Flags = 0;
LocalClassInfoArray->Classes[i].IsVendor = IsVendor; LocalClassInfoArray->Classes[i].Flags = Flags;
i ++; }
*Classes = LocalClassInfoArray; Result = ERROR_SUCCESS;
Cleanup:
(void) MemArrayFree(&ClassAttribs, MemFreeFunc); return Result; }
//================================================================================
// get all optinos and get all option values code
//================================================================================
BOOL TripletNewlyAdded( // check to see if triplet is old or new
IN PARRAY UClasses, // array of strings
IN PARRAY VClasses, // array of strings again
IN PARRAY IsVendorVals, // this is an array of booleans..
IN LPWSTR UClass, // user class
IN LPWSTR VClass, // venodr class
IN ULONG IsVendor // is this vendor or not?
) { ARRAY_LOCATION Loc1, Loc2, Loc3; DWORD Result, Size, ThisIsVendor; LPWSTR ThisUClass, ThisVClass;
Result = MemArrayInitLoc(UClasses, &Loc1); Result = MemArrayInitLoc(VClasses, &Loc2); Result = MemArrayInitLoc(IsVendorVals, &Loc3); for( ; ERROR_FILE_NOT_FOUND != Result ; Result = MemArrayNextLoc(UClasses, &Loc1), Result = MemArrayNextLoc(VClasses, &Loc2), Result = MemArrayNextLoc(IsVendorVals, &Loc3) ) { MemArrayGetElement(UClasses, &Loc1, &ThisUClass); MemArrayGetElement(VClasses, &Loc2, &ThisVClass); MemArrayGetElement(IsVendorVals, &Loc3, (LPVOID *)&ThisIsVendor);
if( ThisIsVendor != IsVendor ) continue;
if( NULL == ThisUClass && NULL != UClass || NULL == UClass && NULL != ThisUClass ) continue; if( NULL != ThisUClass && 0 != wcscmp(ThisUClass, UClass) ) continue;
if( NULL == ThisVClass && NULL != VClass || NULL == VClass && NULL != ThisVClass ) continue; if( NULL != ThisVClass && 0 != wcscmp(ThisVClass, VClass) ) continue;
return FALSE; // triplet already found!
}
// New triplet try to add..
Result = MemArrayAddElement(IsVendorVals, ULongToPtr(IsVendor)); if( ERROR_SUCCESS != Result ) return FALSE;
Result = MemArrayAddElement(VClasses, VClass); if( ERROR_SUCCESS != Result ) return FALSE;
Result = MemArrayAddElement(UClasses, UClass); if ( ERROR_SUCCESS != Result ) return FALSE;
return TRUE; }
DWORD ClassifyAndAddOptionValues( // find if this combo is alreayd there?
IN PEATTRIB ThisAttrib, // attribute to process
IN PARRAY UClasses, // array of user class strings +
IN PARRAY VClasses, // array of vernor class strings +
IN PARRAY IsVendorVals, // array of isvendor values
IN OUT PULONG StringSpace, // amout of space reqd to store strings
IN OUT PULONG BinSpace, // amount of space required to store bins..
IN OUT PULONG OptionCount // # of option values in all.
) { ULONG Err, Size; LPWSTR UClass, VClass; ULONG IsVendor;
UClass = IS_STRING4_PRESENT(ThisAttrib)? ThisAttrib->String4 : NULL; VClass = IS_STRING3_PRESENT(ThisAttrib)? ThisAttrib->String3 : NULL; IsVendor = CheckForVendor(ThisAttrib->Dword1, TRUE);
if( TripletNewlyAdded(UClasses, VClasses, IsVendorVals, UClass, VClass, IsVendor) ) { // this triplet was not present before but was just added... need to make space..
if( UClass ) (*StringSpace) += 1 + wcslen(UClass); if( VClass ) (*StringSpace) += 1 + wcslen(VClass); }
Size = 0; Err = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ NULL, /* OptBuf */ NULL, /* Size */ &Size // just calculate the size..
); if( ERROR_MORE_DATA != Err && ERROR_SUCCESS != Err ) { return Err; // oops strange error..
}
(*BinSpace) += Size; // ok additional binary space is this..
(*OptionCount) ++; // one more option..
return ERROR_SUCCESS; }
DWORD CalculateOptionValuesSize( // amount of space required for storing...
IN ULONG nElements, // # of triples of <classid/vendorid/isvendor>
IN ULONG StringSpace, // # of WCHARs of strings requried
IN ULONG BinSpace, // # of bytes of space requried for storage of bin..
IN ULONG OptCount // total # of options values
) { ULONG Size; // return value.
DHCP_ALL_OPTION_VALUES AllValues;
// basic strucutre
Size = ROUND_UP_COUNT(sizeof(AllValues), ALIGN_WORST);
// array of triplets
Size += nElements * ( sizeof(*(AllValues.Options)) ); Size = ROUND_UP_COUNT( Size, ALIGN_WORST);
// each triplet also has an array in it.. the basic struc..
Size += nElements * ( sizeof(*(AllValues.Options->OptionsArray)) ); Size = ROUND_UP_COUNT( Size, ALIGN_WORST);
// now comes the arrays of options actually
Size += OptCount * sizeof(DHCP_OPTION_VALUE); Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
// now the space to store the strings..
Size += sizeof(WCHAR)*StringSpace;
// now to store the binaries..
Size += BinSpace;
return Size; }
DWORD AddSpecificOptionValues( // for this triple, add all options to array
IN OUT LPDHCP_OPTION_VALUE_ARRAY Values, // array to fill
IN LPWSTR UClass, // the user class of this set of values
IN LPWSTR VClass, // the vendor class of this set of values
IN ULONG IsVendor, // is it vendor or not?
IN PARRAY InputValues, // array of PEATTRIB types from DS
IN OUT LPDHCP_OPTION_VALUE *OptionValues, // use this for space and update it..
IN OUT LPBYTE *Ptr // use this for binary space and update it..
) { ARRAY_LOCATION Loc; PEATTRIB ThisAttrib; DWORD Result, Size, ThisIsVendor; LPWSTR ThisUClass, ThisVClass;
Values->NumElements = 0; Values->Values = (*OptionValues);
for( Result = MemArrayInitLoc(InputValues, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; Result = MemArrayNextLoc(InputValues, &Loc) ) { MemArrayGetElement(InputValues, &Loc, &ThisAttrib);
ThisUClass = IS_STRING4_PRESENT(ThisAttrib)? ThisAttrib->String4 : NULL; ThisVClass = IS_STRING3_PRESENT(ThisAttrib)? ThisAttrib->String3 : NULL; ThisIsVendor = CheckForVendor(ThisAttrib->Dword1, TRUE);
if( ThisIsVendor != IsVendor ) continue;
if( NULL == ThisUClass && NULL != UClass || NULL == UClass && NULL != ThisUClass ) continue; if( NULL != ThisUClass && 0 != wcscmp(ThisUClass, UClass) ) continue;
if( NULL == ThisVClass && NULL != VClass || NULL == VClass && NULL != ThisVClass ) continue; if( NULL != ThisVClass && 0 != wcscmp(ThisVClass, VClass) ) continue;
// matched.. increase count.. convert option.. move pointers..
Values->NumElements ++;
(*OptionValues)->OptionID = ThisAttrib->Dword1; Size = 0xFFFFFFFF; // dont know size but definitely enough
Result = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ &(*OptionValues)->Value, /* OptBuf */ (*Ptr), /* Size */ &Size // just calculate the size..
); if( ERROR_MORE_DATA != Result && ERROR_SUCCESS != Result ) { return Result; // oops strange error..
}
(*OptionValues) ++; (*Ptr) += Size; }
return ERROR_SUCCESS; }
DWORD FillOptionValues( // fill optiosn according to pattern laid out above..
IN PARRAY Options, // teh options to fill
IN PARRAY UClasses, // the user classes
IN PARRAY VClasses, // the vendor classes
IN PARRAY IsVendorVals, // Isvenodr values
IN ULONG StringSpace, // how much space for strings?
IN ULONG BinSpace, // how much space for bins?
IN ULONG OptCount, // total # of options
OUT LPDHCP_ALL_OPTION_VALUES Values // fill this out and returns
) { DHCP_ALL_OPTION_VALUES AllValues; ULONG Result, nElements, Size; LPBYTE Ptr = (LPBYTE)Values; LPWSTR Strings; LPDHCP_OPTION_VALUE OptionValuesArray; int i; ARRAY_LOCATION Loc1, Loc2, Loc3; LPVOID ThisElt;
// basic strucutre
Size = ROUND_UP_COUNT(sizeof(AllValues), ALIGN_WORST); Ptr = Size + (LPBYTE)Values;
Values->NumElements = nElements = MemArraySize(UClasses); Values->Flags = 0; Values->Options = (LPVOID)Ptr;
// array of triplets
Size += nElements * ( sizeof(*(AllValues.Options)) ); Size = ROUND_UP_COUNT( Size, ALIGN_WORST); Ptr = Size + (LPBYTE)Values;
// each triplet also has an array in it.. the basic struc..
for( i = 0; i < (int)nElements; i ++ ) { Values->Options[i].OptionsArray = (LPVOID)Ptr; Ptr += sizeof(*(AllValues.Options->OptionsArray)); }
Size += nElements * ( sizeof(*(AllValues.Options->OptionsArray)) ); Size = ROUND_UP_COUNT( Size, ALIGN_WORST); Ptr = Size + (LPBYTE)Values;
// now comes the arrays of options actually
OptionValuesArray = (LPVOID) Ptr;
Size += OptCount * sizeof(DHCP_OPTION_VALUE); Size = ROUND_UP_COUNT(Size, ALIGN_WORST); Ptr = Size + (LPBYTE)Values;
// now the space to store the strings..
Strings = (LPWSTR)Ptr; Size += sizeof(WCHAR)*StringSpace;
// now to store the binaries..
Ptr = Size + (LPBYTE)Values; Size += BinSpace;
// now do the filling in earnestly.
MemArrayInitLoc(UClasses, &Loc1); MemArrayInitLoc(VClasses, &Loc2); MemArrayInitLoc(IsVendorVals, &Loc3); for( i = 0; i < (int)nElements ; i ++ ) { LPWSTR UClass, VClass; ULONG IsVendor;
MemArrayGetElement(UClasses, &Loc1, &UClass); MemArrayGetElement(VClasses, &Loc2, &VClass); MemArrayGetElement(IsVendorVals, &Loc3, (LPVOID *)&IsVendor);
MemArrayNextLoc(UClasses, &Loc1); MemArrayNextLoc(VClasses, &Loc2); MemArrayNextLoc(IsVendorVals, &Loc3);
if( NULL == UClass ) { Values->Options[i].ClassName = NULL; } else { Values->Options[i].ClassName = Strings; wcscpy(Strings, UClass); Strings += 1 + wcslen(UClass); }
if( NULL == VClass ) { Values->Options[i].VendorName = NULL; } else { Values->Options[i].VendorName = Strings; wcscpy(Strings, VClass); Strings += 1 + wcslen(VClass); }
Values->Options[i].IsVendor = IsVendor;
Result = AddSpecificOptionValues( Values->Options[i].OptionsArray, UClass, VClass, IsVendor, Options, &OptionValuesArray, &Ptr );
if( ERROR_SUCCESS != Result ) return Result; }
return ERROR_SUCCESS; }
//BeginExport(function)
//DOC This function retrieves all the option valuesdefined for this object frm th dS
DWORD DhcpDsGetAllOptionValues( IN LPSTORE_HANDLE hDhcpC, IN LPSTORE_HANDLE hObject, IN DWORD Reserved, OUT LPDHCP_ALL_OPTION_VALUES *OptionValues ) //EndExport(function)
{ DWORD Result, Result2, unused, Size, Size2, i; DWORD AllocSize; ARRAY OptAttribs; PEATTRIB ThisAttrib; ARRAY_LOCATION Loc; LPDHCP_OPTION_VALUE_ARRAY LocalOptionValueArray; LPBYTE Ptr; ARRAY UserClassNames; ARRAY VendorClassNames; ARRAY IsVendorValues; ULONG StringSpace, BinSpace; ULONG OptionCount, ElementCount;
*OptionValues = NULL; LocalOptionValueArray = NULL; MemArrayInit(&OptAttribs); Result = DhcpDsGetLists( // get list of options frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hObject, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ NULL, /* OptionsLocation */ NULL, /* Options */ &OptAttribs, /* Classes */ NULL ); // if( ERROR_SUCCESS != Result ) return Result;
StringSpace = 0; BinSpace = 0; OptionCount = 0; MemArrayInit(&UserClassNames); MemArrayInit(&VendorClassNames); MemArrayInit(&IsVendorValues); for( Result = MemArrayInitLoc(&OptAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // go thru each option, calc size
Result = MemArrayNextLoc(&OptAttribs, &Loc) ) { Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_DWORD1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) { continue; // illegal attrib, or not this opt
}
Result = ClassifyAndAddOptionValues( ThisAttrib, &UserClassNames, &VendorClassNames, &IsVendorValues, &StringSpace, &BinSpace, &OptionCount ); if( ERROR_SUCCESS != Result ) goto Cleanup; }
// total space required calculation...
ElementCount = MemArraySize(&UserClassNames); // same as vendor class etc..
Size = CalculateOptionValuesSize(ElementCount, StringSpace, BinSpace, OptionCount);
(*OptionValues) = MemAlloc(Size); if( NULL == (*OptionValues) ) { Result = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
Result = FillOptionValues( &OptAttribs, &UserClassNames, &VendorClassNames, &IsVendorValues, StringSpace, BinSpace, OptionCount, (*OptionValues) ); if( ERROR_SUCCESS != Result ) { MemFree(*OptionValues); *OptionValues = NULL; }
Cleanup: MemArrayFree(&OptAttribs, MemFreeFunc); MemArrayFree(&UserClassNames, MemFreeFunc); MemArrayFree(&VendorClassNames, MemFreeFunc); MemArrayFree(&IsVendorValues, MemFreeFunc);
return Result; }
DWORD ClassifyAndAddOption( // classify as vendor/non-vendor etc
IN PEATTRIB ThisAttrib, // attrib to classify
IN PULONG StringSpace, // add to this the space reqd for strings
IN PULONG BinSpace, // add to this the space reqd for bin.
IN PULONG VendorCount, // increment if vendor
IN PULONG NonVendorCount // increment if non-vendor
) { BOOL IsVendor; ULONG Result, Size;
if( CheckForVendor(ThisAttrib->Dword1, TRUE) ) { (*VendorCount) ++; // vendor specific option..
IsVendor = TRUE; if( IS_STRING3_PRESENT(ThisAttrib) ) { // got a class name
(*StringSpace) += 1+wcslen(ThisAttrib->String3); } } else { (*NonVendorCount) ++; // not a vendor option
IsVendor = FALSE; }
(*StringSpace) += 1+wcslen(ThisAttrib->String1); if( IS_STRING2_PRESENT(ThisAttrib) ) { // string1 is name, string2 is comment
(*StringSpace) += 1+wcslen(ThisAttrib->String2); }
Size = 0; Result = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ NULL, /* OptBuf */ NULL, /* Size */ &Size ); if( ERROR_MORE_DATA != Result && ERROR_SUCCESS != Result ) { return Result; }
(*BinSpace) += Size; return ERROR_SUCCESS; }
DWORD CalculateOptionsSize( // calc amt storage reqd for this..
IN ULONG VendorCount, // # of vendor options
IN ULONG NonVendorCount,// # of non-vendor options
IN ULONG StringSpace, // # of WCHAR string chars
IN ULONG BinSpace // # of bytes for binary data..
) { ULONG Size; LPDHCP_ALL_OPTIONS AllOptions; // dummy structure..
// First comes the structure itself
Size = ROUND_UP_COUNT(sizeof(*AllOptions), ALIGN_WORST);
// Next comes the space for a NonVendorOptions array
Size += sizeof(*(AllOptions->NonVendorOptions)); Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
// Next comes the non-vendor optiosn themselves
Size += NonVendorCount * sizeof(DHCP_OPTION); Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
// Next comes the vendor options structure..
Size += VendorCount * sizeof(*(AllOptions->VendorOptions)); Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
// Next store the strings..
Size += sizeof(WCHAR)*StringSpace;
// Next store the binary information..
Size += BinSpace;
return Size; }
DWORD AddSpecificOptions( // fill in the structure of optiosn..
IN OUT LPDHCP_ALL_OPTIONS AllOptions, // this is the structure to fill in
IN LPWSTR Strings, // Buffer to use to fill in all strings
IN LPBYTE BinarySpace, // this is the space to use for bin..
IN PARRAY OptDefs // the array to pick off hte options from
) { ULONG Err, Size; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib; ULONG nVendorOpts, nNonVendorOpts; BOOL IsVendor; ULONG OptId, OptType; LPWSTR OptionName; LPWSTR OptionComment; LPWSTR VendorName; LPDHCP_OPTION ThisOption;
AllOptions->Flags = 0; nVendorOpts = nNonVendorOpts = 0;
for( Err = MemArrayInitLoc(OptDefs, &Loc) ; ERROR_SUCCESS == Err ; Err = MemArrayNextLoc(OptDefs, &Loc) ) { // process each option
Err = MemArrayGetElement(OptDefs, &Loc, &ThisAttrib);
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
continue; // skip it
}
IsVendor = CheckForVendor(ThisAttrib->Dword1, TRUE ); OptId = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE); OptType = IS_FLAGS1_PRESENT(ThisAttrib) ? ThisAttrib->Flags1 : 0; OptionName = ThisAttrib->String1; OptionComment = IS_STRING2_PRESENT(ThisAttrib) ? ThisAttrib->String2 : NULL; VendorName = IS_STRING3_PRESENT(ThisAttrib) ? ThisAttrib->String3 : NULL;
if( !IsVendor ) { // fill in the non-vendor part..
ThisOption = &AllOptions->NonVendorOptions->Options[nNonVendorOpts++]; } else { ThisOption = &AllOptions->VendorOptions[nVendorOpts].Option; if( !VendorName ) { AllOptions->VendorOptions[nVendorOpts].VendorName = NULL; } else { wcscpy(Strings, VendorName); AllOptions->VendorOptions[nVendorOpts].VendorName = Strings; Strings += 1+wcslen(Strings); } AllOptions->VendorOptions[nVendorOpts++].ClassName = NULL; }
Size = 0xFFFFFFFF; // databuffer size is sufficient.. but unkonwn..
Err = DhcpConvertOptionRegToRPCFormat2( /* Buffer */ ThisAttrib->Binary1, /* BufferSize */ ThisAttrib->BinLen1, /* Option */ &ThisOption->DefaultValue, /* OptBuf */ BinarySpace, /* Size */ &Size ); if( ERROR_SUCCESS != Err ) return Err; // barf
BinarySpace += Size; // update sapce ..
ThisOption->OptionID = OptId; ThisOption->OptionType = OptType; ThisOption->OptionName = Strings; wcscpy(Strings, OptionName); Strings += 1+wcslen(Strings); if( NULL == OptionComment ) { ThisOption->OptionComment = NULL; } else { ThisOption->OptionComment = Strings; wcscpy(Strings, OptionComment); Strings += 1 + wcslen(Strings); }
}
if( AllOptions->NumVendorOptions != nVendorOpts || AllOptions->NonVendorOptions->NumElements != nNonVendorOpts ) { return ERROR_INVALID_DATA; }
return ERROR_SUCCESS; }
DWORD FillOptions( // fill in the optinos..
IN PARRAY OptDefs, // each attrib isz an option to fill in
IN ULONG VendorCount, // # of vendor options
IN ULONG NonVendorCount,// # of non-vendor options
IN ULONG StringSpace, // sapce for strings
IN ULONG BinSpace, // space for binary..
OUT LPDHCP_ALL_OPTIONS AllOptions // fill this in..
) { LPBYTE Ptr; ULONG Size,Result; LPWSTR Strings; LPBYTE Binary;
// first comes the structure itself..
AllOptions->Flags = 0; AllOptions->NumVendorOptions = VendorCount; Size = ROUND_UP_COUNT(sizeof(*AllOptions), ALIGN_WORST); Ptr = Size + (LPBYTE)AllOptions;
// next comes NonVendorOptions array
AllOptions->NonVendorOptions = (LPVOID)Ptr; AllOptions->NonVendorOptions->NumElements = NonVendorCount; Size += sizeof(*(AllOptions->NonVendorOptions)); Size = ROUND_UP_COUNT(Size, ALIGN_WORST); Ptr = Size + (LPBYTE)AllOptions;
if( 0 == NonVendorCount ) { AllOptions->NonVendorOptions->Options = NULL; } else { AllOptions->NonVendorOptions->Options = (LPVOID)Ptr; }
// Next comes the non-vendor optiosn themselves
Size += NonVendorCount * sizeof(DHCP_OPTION); Size = ROUND_UP_COUNT(Size, ALIGN_WORST); Ptr = Size + (LPBYTE)AllOptions;
// Next comes the vendor options structure..
AllOptions->VendorOptions = (LPVOID)Ptr;
Size += VendorCount * sizeof(*(AllOptions->VendorOptions)); Size = ROUND_UP_COUNT(Size, ALIGN_WORST); Ptr = Size + (LPBYTE)AllOptions;
// Next store the strings..
Strings = (LPWSTR)Ptr; Size += sizeof(WCHAR)*StringSpace; Ptr = Size + (LPBYTE)AllOptions;
// Next store the binary information..
Binary = Ptr;
return AddSpecificOptions( AllOptions, Strings, Binary, OptDefs ); }
//BeginExport(function)
//DOC This function retrieves all the optiosn defined for this server.. frm the DS
DWORD DhcpDsGetAllOptions( IN LPSTORE_HANDLE hDhcpC, IN LPSTORE_HANDLE hServer, IN DWORD Reserved, OUT LPDHCP_ALL_OPTIONS *Options ) //EndExport(function)
{ DWORD Result, Result2, unused, Size, Size2, i, AllocSize; ARRAY OptDefAttribs; PEATTRIB ThisAttrib; EATTRIB DummyAttrib; ARRAY_LOCATION Loc; LPDHCP_OPTION_ARRAY OptArray; ULONG StringSpace, BinSpace; ULONG VendorCount, NonVendorCount;
*Options = NULL; MemArrayInit(&OptDefAttribs); Result = DhcpDsGetLists( // get list of opt defs frm DS
/* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0xFFFFFFFF, /* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescription */ &OptDefAttribs, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
StringSpace = 0; BinSpace = 0; VendorCount = NonVendorCount = 0;
for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
Result = MemArrayNextLoc(&OptDefAttribs, &Loc) ) { Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
continue; // skip it
}
Result = ClassifyAndAddOption( ThisAttrib, &StringSpace, &BinSpace, &VendorCount, &NonVendorCount ); if( ERROR_SUCCESS != Result ) goto Cleanup; }
Size = CalculateOptionsSize( VendorCount, NonVendorCount, StringSpace, BinSpace );
(*Options) = MemAlloc(Size); if( NULL == (*Options) ) { Result = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
Result = FillOptions( &OptDefAttribs, VendorCount, NonVendorCount, StringSpace, BinSpace, (*Options) ); if( ERROR_SUCCESS == Result ) return ERROR_SUCCESS;
MemFree(*Options); *Options = NULL;
Cleanup: MemArrayFree(&OptDefAttribs, MemFreeFunc);
return Result; }
//================================================================================
// End of file
//================================================================================
|