|
|
/*++
Copyright (C) 2000 Microsoft Corporation
Module Name:
mmfile.c
Abstract;
This file contains code to read/write MM data structures from/to internal file format.. code is nearly ripped off of server\dbconfig.c
--*/
#include <precomp.h>
#include "server\uniqid.h"
typedef struct _DB_CREATE_CONTEXT { IN ULONG Index; IN PM_SERVER Server; IN PM_CLASSDEF UserClass, VendorClass; IN PM_SUBNET Subnet; IN PM_RESERVATION Reservation;
} DB_CREATE_CONTEXT, *PDB_CREATE_CONTEXT;
//
// types of records
//
enum { DBCFG_CLASS, DBCFG_OPT, DBCFG_OPTDEF, DBCFG_SCOPE, DBCFG_MSCOPE, DBCFG_RANGE, DBCFG_EXCL, DBCFG_RESERVATION, DBCFG_END };
//
// attributes/fields
//
enum { DBCFG_INDEX, DBCFG_TYPE, DBCFG_SUBTYPE, DBCFG_FLAGS, DBCFG_NAME, DBCFG_COMMENT, DBCFG_INFO, DBCFG_OPTION_ID, DBCFG_OPTION_USER, DBCFG_OPTION_VENDOR, DBCFG_IPADDRESS, DBCFG_MASK, DBCFG_SUPERSCOPE, DBCFG_MSCOPEID, DBCFG_MSCOPELANG, DBCFG_MSCOPETTL, DBCFG_MSCOPE_EXPIRY, DBCFG_RANGE_START, DBCFG_RANGE_END, DBCFG_RANGE_MASK, DBCFG_BOOTP_ALLOCATED, DBCFG_BOOTP_MAX, DBCFG_LAST_COLUMN };
typedef struct _DBCFG_ENTRY { ULONG Bitmasks; // indicates which of the fields below is present
ULONG Index; ULONG Type, SubType, Flags; LPWSTR Name, Comment; PUCHAR Info; ULONG OptionId; LPWSTR UserClass, VendorClass; ULONG IpAddress, Mask; LPWSTR SuperScope; ULONG MscopeId; LPWSTR MscopeLang; ULONG Ttl; FILETIME ExpiryTime; ULONG RangeStart, RangeEnd, RangeMask; ULONG BootpAllocated, BootpMax;
ULONG InfoSize; PVOID Buf; } DBCFG_ENTRY, *PDBCFG_ENTRY;
typedef struct _DBCFG_MAP { DWORD Offset, Size; } DBCFG_MAP;
DBCFG_MAP EntryMap[] = { FIELD_OFFSET(DBCFG_ENTRY,Index), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,Type), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,SubType), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,Flags), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,Name), 0, FIELD_OFFSET(DBCFG_ENTRY,Comment), 0, FIELD_OFFSET(DBCFG_ENTRY,Info), 0, FIELD_OFFSET(DBCFG_ENTRY,OptionId), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,UserClass), 0, FIELD_OFFSET(DBCFG_ENTRY,VendorClass), 0, FIELD_OFFSET(DBCFG_ENTRY,IpAddress), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,Mask), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,SuperScope), 0, FIELD_OFFSET(DBCFG_ENTRY,MscopeId), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,MscopeLang), 0, FIELD_OFFSET(DBCFG_ENTRY,Ttl), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,ExpiryTime), sizeof(FILETIME), FIELD_OFFSET(DBCFG_ENTRY,RangeStart), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,RangeEnd), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,RangeMask), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,BootpAllocated), sizeof(DWORD), FIELD_OFFSET(DBCFG_ENTRY,BootpMax), sizeof(DWORD) };
DWORD Bitmasks[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x010000, 0x020000, 0x040000, 0x080000, 0x100000, 0x200000, 0x400000, 0x80000, };
DWORD CreateDbEntry( IN PDBCFG_ENTRY Entry ) { DWORD Error, Size, i, Offset; PVOID Data; WORD Buffer[4096]; Offset = 0; for( i = 0; i < DBCFG_LAST_COLUMN; i ++ ) { if( (Entry->Bitmasks & Bitmasks[i]) == 0 ) { continue; }
Size = EntryMap[i].Size; Data = EntryMap[i].Offset + (LPBYTE)Entry;
if( i == DBCFG_INFO ) { //
// Skip info -- it is added at end
//
continue; } else if( 0 == Size ) { //
// Calculate the size of the string
//
Data = *(LPWSTR *)Data;
if( NULL != Data ) Size = sizeof(WCHAR)*( 1 + wcslen(Data)); }
if( 0 == Size ) continue;
Buffer[Offset++] = (WORD)i; Buffer[Offset++] = (WORD)Size; memcpy(&Buffer[Offset], Data, Size); Offset += (Size + sizeof(WORD) - 1 )/sizeof(WORD);
}
//
// add info at the end.
//
i = DBCFG_INFO; if( Entry->Bitmasks & Bitmasks[i]) { Size = EntryMap[i].Size; Data = EntryMap[i].Offset + (LPBYTE)Entry; Data = *(PUCHAR *)Data; if( NULL != Data ) Size = Entry->InfoSize; if( 0 != Size ) {
Buffer[Offset++] = (WORD)i; Buffer[Offset++] = (WORD)Size; memcpy(&Buffer[Offset], Data, Size); Offset += (Size + sizeof(WORD) - 1 )/sizeof(WORD); } }
Buffer[Offset++] = DBCFG_LAST_COLUMN+1; Buffer[Offset++] = 0; //
// Write the record onto file
//
return AddRecordNoSize( (LPBYTE)Buffer, Offset*sizeof(WORD)); }
DWORD CreateClassEntry( IN ULONG Index, IN PM_CLASSDEF Class ) { DBCFG_ENTRY Entry;
//
// IsVendor, Type, Name, Comment, nBytes, ActualBytes
//
ZeroMemory(&Entry, sizeof(Entry)); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] | Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_FLAGS] | Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] | Bitmasks[DBCFG_INFO] );
Entry.Index = Index; Entry.Type = DBCFG_CLASS;
Entry.Flags = Class->IsVendor; Entry.SubType = Class->Type; Entry.Name = Class->Name; Entry.Comment = Class->Comment; Entry.Info = Class->ActualBytes; Entry.InfoSize = Class->nBytes;
return CreateDbEntry( &Entry ); }
DWORD CreateOptDefEntry( IN ULONG Index, IN PM_OPTDEF OptDef, IN PM_CLASSDEF UserClass, IN PM_CLASSDEF VendorClass ) { DBCFG_ENTRY Entry;
//
// OptId, Type, OptName, OptComment, OptVal, OptValLen,
// User, Vendor
//
ZeroMemory(&Entry, sizeof(Entry)); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] | Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_OPTION_ID] | Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] | Bitmasks[DBCFG_INFO] | Bitmasks[DBCFG_OPTION_USER] | Bitmasks[DBCFG_OPTION_VENDOR] );
Entry.Index = Index; Entry.Type = DBCFG_OPTDEF;
Entry.OptionId = OptDef->OptId; Entry.SubType = OptDef->Type; Entry.Name = OptDef->OptName; Entry.Comment = OptDef->OptComment; Entry.Info = OptDef->OptVal; Entry.InfoSize = OptDef->OptValLen; if( UserClass) Entry.UserClass = UserClass->Name; if( VendorClass) Entry.VendorClass = VendorClass->Name; return CreateDbEntry( &Entry ); }
DWORD CreateOptionEntry( IN ULONG Index, IN PM_OPTION Option, IN PM_CLASSDEF UserClass, IN PM_CLASSDEF VendorClass, IN PM_SUBNET Subnet, IN PM_RESERVATION Reservation ) { DBCFG_ENTRY Entry; //
// OptId, Len, Val, User, Vendor
//
ZeroMemory(&Entry, sizeof(Entry)); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] | Bitmasks[DBCFG_OPTION_ID] | Bitmasks[DBCFG_INFO] | Bitmasks[DBCFG_OPTION_USER] | Bitmasks[DBCFG_OPTION_VENDOR] );
if( Reservation ) { Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS]; Entry.IpAddress = Reservation->Address; } else if( Subnet && Subnet->fSubnet ) { Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS]; Entry.IpAddress = Subnet->Address; } else if( Subnet && !Subnet->fSubnet ) { Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID]; Entry.MscopeId = Subnet->MScopeId; } Entry.Index = Index; Entry.Type = DBCFG_OPT;
Entry.OptionId = Option->OptId; Entry.Info = Option->Val; Entry.InfoSize = Option->Len; if( UserClass) Entry.UserClass = UserClass->Name; if( VendorClass) Entry.VendorClass = VendorClass->Name;
return CreateDbEntry( &Entry ); } DWORD CreateScopeEntry( IN ULONG Index, IN PM_SUBNET Subnet, IN PM_SSCOPE SScope ) { DBCFG_ENTRY Entry;
//
// State, Policy, ExpiryTime, Name, Description
//
ZeroMemory(&Entry, sizeof(Entry)); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] | Bitmasks[DBCFG_SUBTYPE] | Bitmasks[DBCFG_FLAGS] | Bitmasks[DBCFG_NAME] | Bitmasks[DBCFG_COMMENT] );
if( Subnet->fSubnet ) { Entry.Bitmasks |= ( Bitmasks[DBCFG_IPADDRESS] | Bitmasks[DBCFG_MASK] | Bitmasks[DBCFG_SUPERSCOPE] ); Entry.IpAddress = Subnet->Address; Entry.Mask = Subnet->Mask; if( SScope ) Entry.SuperScope = SScope->Name; } else { Entry.Bitmasks |= ( Bitmasks[DBCFG_MSCOPEID] | Bitmasks[DBCFG_MSCOPETTL] | Bitmasks[DBCFG_MSCOPELANG] | Bitmasks[DBCFG_MSCOPE_EXPIRY] );
Entry.MscopeId = Subnet->MScopeId; Entry.Ttl = Subnet->TTL; Entry.MscopeLang = Subnet->LangTag; Entry.ExpiryTime = *(FILETIME *)&Subnet->ExpiryTime; } Entry.Index = Index; Entry.Type = Subnet->fSubnet ? DBCFG_SCOPE : DBCFG_MSCOPE ;
Entry.SubType = Subnet->State; Entry.Flags = Subnet->Policy; Entry.Name = Subnet->Name; Entry.Comment = Subnet->Description; return CreateDbEntry( &Entry ); } DWORD CreateRangeEntry( IN ULONG Index, IN PM_RANGE Range, IN PM_SUBNET Subnet ) { DBCFG_ENTRY Entry;
//
// Start, End, Mask, State, BootpAllocated, MaxBootpAllowed
//
ZeroMemory(&Entry, sizeof(Entry)); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] | Bitmasks[DBCFG_RANGE_START] | Bitmasks[DBCFG_RANGE_END] | Bitmasks[DBCFG_RANGE_MASK] | Bitmasks[DBCFG_FLAGS] | Bitmasks[DBCFG_BOOTP_ALLOCATED] | Bitmasks[DBCFG_BOOTP_MAX] );
if( Subnet->fSubnet ) { Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS]; Entry.IpAddress = Subnet->Address; } else { Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID]; Entry.MscopeId = Subnet->MScopeId; } Entry.Index = Index; Entry.Type = DBCFG_RANGE;
Entry.RangeStart = Range->Start; Entry.RangeEnd = Range->End; Entry.RangeMask = Range->Mask; Entry.Flags = Range->State; Entry.BootpAllocated = Range->BootpAllocated; Entry.BootpMax = Range->MaxBootpAllowed; return CreateDbEntry( &Entry ); }
DWORD CreateExclEntry( IN ULONG Index, IN PM_EXCL Excl, IN PM_SUBNET Subnet ) { DBCFG_ENTRY Entry;
//
// Start, End
//
ZeroMemory(&Entry, sizeof(Entry)); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] | Bitmasks[DBCFG_RANGE_START] | Bitmasks[DBCFG_RANGE_END] );
if( Subnet->fSubnet ) { Entry.Bitmasks |= Bitmasks[DBCFG_IPADDRESS]; Entry.IpAddress = Subnet->Address; } else { Entry.Bitmasks |= Bitmasks[DBCFG_MSCOPEID]; Entry.MscopeId = Subnet->MScopeId; } Entry.Index = Index; Entry.Type = DBCFG_EXCL;
Entry.RangeStart = Excl->Start; Entry.RangeEnd = Excl->End; return CreateDbEntry( &Entry ); }
DWORD CreateReservationEntry( IN ULONG Index, IN PM_RESERVATION Reservation ) { DBCFG_ENTRY Entry;
//
// Address, Flags, nBytes, ClientUID
//
ZeroMemory(&Entry, sizeof(Entry)); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] | Bitmasks[DBCFG_IPADDRESS] | Bitmasks[DBCFG_INFO] | Bitmasks[DBCFG_FLAGS] );
Entry.Index = Index; Entry.Type = DBCFG_RESERVATION;
Entry.IpAddress = Reservation->Address; Entry.Flags = Reservation->Flags; Entry.Info = Reservation->ClientUID; Entry.InfoSize = Reservation->nBytes; return CreateDbEntry( &Entry ); }
DWORD IterateArrayWithDbCreateRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PARRAY Array, IN DWORD (*Routine)( IN PDB_CREATE_CONTEXT Ctxt, IN PVOID ArrayElement ) ) { ARRAY_LOCATION Loc; DWORD Error; PVOID Element; Error = MemArrayInitLoc( Array, &Loc ); while( NO_ERROR == Error ) {
Error = MemArrayGetElement( Array, &Loc, &Element ); ASSERT( NO_ERROR == Error && NULL != Element );
Ctxt->Index ++;
Error = Routine( Ctxt, Element ); if( NO_ERROR != Error ) return Error;
Error = MemArrayNextLoc( Array, &Loc ); }
if( ERROR_FILE_NOT_FOUND == Error ) return NO_ERROR; return Error; } DWORD DbCreateClassRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_CLASSDEF Class ) { return CreateClassEntry( Ctxt->Index, Class ); }
DWORD DbCreateOptDefRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_OPTDEF OptDef ) { return CreateOptDefEntry( Ctxt->Index, OptDef, Ctxt->UserClass, Ctxt->VendorClass ); }
DWORD DbCreateOptClassDefRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_OPTCLASSDEFL_ONE OptClassDef ) { DWORD Error;
if( 0 == MemArraySize(&OptClassDef->OptDefList.OptDefArray) ) { return NO_ERROR; } if( 0 == OptClassDef->ClassId ) { Ctxt->UserClass = NULL; } else { Error = MemServerGetClassDef( Ctxt->Server, OptClassDef->ClassId, NULL, 0, NULL, &Ctxt->UserClass ); ASSERT( NO_ERROR == Error ); if( NO_ERROR != Error ) return Error; }
if( 0 == OptClassDef->VendorId ) { Ctxt->VendorClass = NULL; } else { Error = MemServerGetClassDef( Ctxt->Server, OptClassDef->VendorId, NULL, 0, NULL, &Ctxt->VendorClass ); ASSERT( NO_ERROR == Error ); if( NO_ERROR != Error ) return Error; }
Error = IterateArrayWithDbCreateRoutine( Ctxt, &OptClassDef->OptDefList.OptDefArray, DbCreateOptDefRoutine );
return Error; }
DWORD DbCreateOptionRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_OPTION Option ) { return CreateOptionEntry( Ctxt->Index, Option, Ctxt->UserClass, Ctxt->VendorClass, Ctxt->Subnet, Ctxt->Reservation ); }
DWORD DbCreateOptListRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_ONECLASS_OPTLIST OptList ) { DWORD Error;
if( 0 == MemArraySize(&OptList->OptList) ) { return NO_ERROR; } if( 0 == OptList->ClassId ) { Ctxt->UserClass = NULL; } else { Error = MemServerGetClassDef( Ctxt->Server, OptList->ClassId, NULL, 0, NULL, &Ctxt->UserClass ); ASSERT( NO_ERROR == Error ); if( NO_ERROR != Error ) return Error; }
if( 0 == OptList->VendorId ) { Ctxt->VendorClass = NULL; } else { Error = MemServerGetClassDef( Ctxt->Server, OptList->VendorId, NULL, 0, NULL, &Ctxt->VendorClass ); ASSERT( NO_ERROR == Error ); if( NO_ERROR != Error ) return Error; }
Error = IterateArrayWithDbCreateRoutine( Ctxt, &OptList->OptList, DbCreateOptionRoutine );
return Error; }
DWORD DbCreateRangeRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_RANGE Range ) { return CreateRangeEntry( Ctxt->Index, Range, Ctxt->Subnet ); }
DWORD DbCreateExclRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_EXCL Excl ) { return CreateExclEntry( Ctxt->Index, Excl, Ctxt->Subnet ); }
DWORD DbCreateReservationRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_RESERVATION Reservation ) { DWORD Error; Error = CreateReservationEntry( Ctxt->Index, Reservation ); if( NO_ERROR != Error ) return Error;
Ctxt->Reservation = Reservation; //
// Now add the options for this reservation
//
return IterateArrayWithDbCreateRoutine( Ctxt, &Reservation->Options.Array, DbCreateOptListRoutine ); }
DWORD DbCreateScopeRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_SUBNET Subnet ) { PM_SSCOPE SScope = NULL; DWORD Error; if( Subnet->fSubnet && Subnet->SuperScopeId ) { Error = MemServerFindSScope( Ctxt->Server, Subnet->SuperScopeId, NULL, &SScope ); if( NO_ERROR != Error ) { SScope = NULL; } }
Error = CreateScopeEntry( Ctxt->Index, Subnet, SScope ); if( NO_ERROR != Error ) return Error;
//
// Initialize the two fields that will get used later
//
Ctxt->Subnet = Subnet; Ctxt->Reservation = NULL;
//
// Now add the options for this scope
//
Error = IterateArrayWithDbCreateRoutine( Ctxt, &Subnet->Options.Array, DbCreateOptListRoutine ); if( NO_ERROR != Error ) return Error;
//
// Now add the ranges and exclusions
//
Error = IterateArrayWithDbCreateRoutine( Ctxt, &Subnet->Ranges, DbCreateRangeRoutine ); if( NO_ERROR != Error ) return Error;
Error = IterateArrayWithDbCreateRoutine( Ctxt, &Subnet->Exclusions, DbCreateExclRoutine ); if( NO_ERROR != Error ) return Error;
//
// Finally, add the reservations
//
return IterateArrayWithDbCreateRoutine( Ctxt, &Subnet->Reservations, DbCreateReservationRoutine ); }
DWORD DbCreateServerRoutine( IN PDB_CREATE_CONTEXT Ctxt, IN PM_SERVER Server ) { DWORD Error; Ctxt->Server = Server;
//
// First look through the classes
//
Error = IterateArrayWithDbCreateRoutine( Ctxt, &Server->ClassDefs.ClassDefArray, DbCreateClassRoutine ); if( NO_ERROR != Error ) return Error;
//
// Next save the option defs
//
Error = IterateArrayWithDbCreateRoutine( Ctxt, &Server->OptDefs.Array, DbCreateOptClassDefRoutine ); if( NO_ERROR != Error ) return Error;
//
// Next save the options
//
Error = IterateArrayWithDbCreateRoutine( Ctxt, &Server->Options.Array, DbCreateOptListRoutine ); if( NO_ERROR != Error ) return Error;
//
// Next save the scopes and mcast scopes
//
Error = IterateArrayWithDbCreateRoutine( Ctxt, &Server->Subnets, DbCreateScopeRoutine ); if( NO_ERROR != Error ) return Error;
return NO_ERROR; }
DWORD SaveConfigurationToFile( IN PM_SERVER Server ) { DB_CREATE_CONTEXT Ctxt; DWORD Error; ZeroMemory( &Ctxt, sizeof(Ctxt) ); Error = DbCreateServerRoutine( &Ctxt, Server ); if( NO_ERROR != Error ) { Tr("DbCreateServerRoutine: %ld\n", Error); } else { //
// Sentinel
//
DBCFG_ENTRY Entry; ZeroMemory( &Entry, sizeof(Entry) ); Entry.Bitmasks = ( Bitmasks[DBCFG_INDEX] | Bitmasks[DBCFG_TYPE] ); Entry.Type = DBCFG_END;
Error = CreateDbEntry( &Entry ); if( NO_ERROR != Error ) { Tr("Create last entry: %ld\n", Error ); } }
Tr("SaveConfigurationToFile: %ld\n", Error); return Error; } DWORD GetColumnFromMemory( IN OUT LPBYTE *Mem, IN OUT ULONG *MemSize, IN ULONG Col, IN OUT PVOID Buffer, IN ULONG BufSize, IN OUT ULONG *CopiedSize ) { WORD *WordMem = (WORD *)*Mem; DWORD Size; if( *MemSize < sizeof(WORD)*2 ) return ERROR_INVALID_DATA; if( Col != WordMem[0] ) return JET_wrnColumnNull;
Size = sizeof(WORD)*( 2 + (WordMem[1]+sizeof(WORD)-1)/sizeof(WORD) ); if( Size > *MemSize ) return ERROR_INVALID_DATA;
if( WordMem[1] >= BufSize ) *CopiedSize = BufSize; else *CopiedSize = WordMem[1];
memcpy(Buffer, &WordMem[2], *CopiedSize ); (*Mem) += Size; (*MemSize) -= Size;
if( WordMem[1] > BufSize ) return JET_wrnBufferTruncated; return NO_ERROR; } DWORD ReadDbEntry( IN OUT LPBYTE *Mem, IN OUT ULONG *MemSize, IN PDBCFG_ENTRY Entry, IN PVOID Buffer, IN ULONG BufSize ) { DWORD Size, CopiedSize, i, OldMemSize, DummySize; JET_ERR JetError; LPVOID Data, Ptr; LPBYTE OldMem;
OldMemSize = *MemSize; OldMem = *Mem; ZeroMemory( Entry, sizeof(*Entry) ); ZeroMemory( Buffer, BufSize ); for( i = 0; i < DBCFG_LAST_COLUMN; i ++ ) {
//
// Info should be read at the very end to avoid screwing
// up alignment as info is binary while the rest of the
// variable size columns are all WCHAR strings
//
if( i == DBCFG_INFO ) continue; Size = EntryMap[i].Size; Data = EntryMap[i].Offset + (LPBYTE)Entry; Ptr = Data; if( 0 == Size ) { //
// Calculate the size of the string
//
Data = Buffer; Size = BufSize; }
JetError = GetColumnFromMemory( Mem, MemSize, i, Data, Size, &CopiedSize );
//
// If the column doesn't exist, continue
//
if( JET_wrnColumnNull == JetError ) continue; if( JET_wrnBufferTruncated == JetError && Data == Buffer ) {
(*Mem) = OldMem; (*MemSize) = OldMemSize; return ERROR_INSUFFICIENT_BUFFER; }
if( NO_ERROR != JetError ) { Tr( "GetColumnFromMemory: %ld\n", JetError ); return JetError; } //
// If it is any of the variable sized params, then
// set the ptr to point to the buffer where the data is
// copied, and also update the buffer.
//
if( Data == Buffer ) { (*(LPVOID *)Ptr) = Buffer; BufSize -= CopiedSize; Buffer = (PVOID)(((PUCHAR)Buffer) + CopiedSize); } else { ASSERT( CopiedSize == Size ); }
//
// Indicate that the column was retrieved successfully
//
Entry->Bitmasks |= Bitmasks[i]; }
//
// Read the info field
//
Size = BufSize; JetError = GetColumnFromMemory( Mem, MemSize, DBCFG_INFO, Buffer, Size, &CopiedSize );
GetColumnFromMemory( Mem, MemSize, DBCFG_LAST_COLUMN+1,NULL, 0, &DummySize); if( JET_wrnColumnNull == JetError ) return NO_ERROR; if( JET_wrnBufferTruncated == JetError ) { (*Mem) = OldMem; (*MemSize) = OldMemSize; return ERROR_INSUFFICIENT_BUFFER; }
if( NO_ERROR != JetError ) { Tr("GetColumnFromMemory: %ld\n", JetError ); return JetError; } Entry->Info = Buffer; Entry->InfoSize = CopiedSize; Entry->Bitmasks |= Bitmasks[DBCFG_INFO];
return NO_ERROR; }
DWORD ReadDbEntryEx( IN OUT LPBYTE *Mem, IN OUT ULONG *MemSize, IN PDBCFG_ENTRY Entry ) { PVOID Buffer; ULONG BufSize; DWORD Error;
Buffer = NULL; BufSize = 512; do { if( NULL != Buffer ) LocalFree(Buffer);
BufSize *= 2; Buffer = LocalAlloc( LPTR, BufSize ); if( NULL == Buffer ) return ERROR_NOT_ENOUGH_MEMORY; Error = ReadDbEntry(Mem, MemSize, Entry, Buffer, BufSize);
} while( ERROR_INSUFFICIENT_BUFFER == Error );
if( !(Entry->Bitmasks & Bitmasks[DBCFG_INDEX]) || !(Entry->Bitmasks & Bitmasks[DBCFG_TYPE]) ) { if( NO_ERROR == Error ) { ASSERT( FALSE ); Error = ERROR_INTERNAL_ERROR; } } if( NO_ERROR != Error ) { LocalFree( Buffer ); return Error; }
Entry->Buf = Buffer; return NO_ERROR; }
DWORD AddDbEntry( IN PM_SERVER Server, IN PDBCFG_ENTRY Entry ) { DWORD UserId, VendorId, SScopeId, Error; PM_SUBNET Subnet; PM_OPTCLASS OptClass; PM_OPTION Option, DelOpt; PM_RANGE DelRange; PM_EXCL DelExcl; PM_RESERVATION Reservation; PM_CLASSDEF ClassDef; PM_SSCOPE SScope; Subnet = NULL; OptClass = NULL; Option = DelOpt = NULL; Reservation = NULL; DelRange = NULL; DelExcl = NULL; UserId = 0; VendorId = 0; SScopeId = 0; if( Entry->UserClass ) { Error = MemServerGetClassDef( Server, 0, Entry->UserClass, 0, NULL, &ClassDef ); ASSERT( NO_ERROR == Error ); if( NO_ERROR != Error ) return Error;
ASSERT( ClassDef->IsVendor == FALSE ); UserId = ClassDef->ClassId; }
if( Entry->VendorClass ) { Error = MemServerGetClassDef( Server, 0, Entry->VendorClass, 0, NULL, &ClassDef ); ASSERT( NO_ERROR == Error ); if( NO_ERROR != Error ) return Error;
ASSERT( ClassDef->IsVendor == TRUE); VendorId = ClassDef->ClassId; }
if( Entry->SuperScope ) { Error = MemServerFindSScope( Server, INVALID_SSCOPE_ID, Entry->SuperScope, &SScope ); if( NO_ERROR == Error ) { SScopeId = SScope->SScopeId; } else if( ERROR_FILE_NOT_FOUND != Error ) { return Error; } else { Error = MemSScopeInit( &SScope, 0, Entry->SuperScope ); if( NO_ERROR != Error ) return Error;
Error = MemServerAddSScope( Server, SScope ); if( NO_ERROR != Error ) { MemSScopeCleanup( SScope ); return Error; } SScopeId = SScope->SScopeId; } } switch( Entry->Type ) { case DBCFG_CLASS : //
// Flags = IsVendor, SubType =Type, Info = ActualBytes
//
return MemServerAddClassDef( Server, MemNewClassId(), Entry->Flags, Entry->Name, Entry->Comment, Entry->InfoSize, Entry->Info, INVALID_UNIQ_ID );
case DBCFG_OPTDEF : //
// OptionId = OptId, SubType = Type, Info = OptVal
//
return MemServerAddOptDef( Server, UserId, VendorId, Entry->OptionId, Entry->Name, Entry->Comment, Entry->SubType, Entry->Info, Entry->InfoSize, INVALID_UNIQ_ID );
case DBCFG_OPT: //
// OptionId = OptId, Info = Val
// If this is a reservation option, address is set to
// reserved client address. If this is a subnet option,
// address is set to subnet address. If this is a mscope
// option, scopeid is set to mscope scopeid. If it is a
// global option, neither address not scopeid is set.
//
if( Entry->Bitmasks & Bitmasks[DBCFG_MSCOPEID] ) { Error = MemServerFindMScope( Server, Entry->MscopeId, NULL, &Subnet ); if( NO_ERROR != Error ) return Error;
OptClass = &Subnet->Options; } else if( 0 == (Entry->Bitmasks & Bitmasks[DBCFG_IPADDRESS] )) { OptClass = &Server->Options; } else { Error = MemServerGetUAddressInfo( Server, Entry->IpAddress, &Subnet, NULL, NULL, &Reservation ); ASSERT( NO_ERROR == Error ); if( NO_ERROR != Error ) return Error;
if( NULL != Reservation ) { OptClass = &Reservation->Options; } else OptClass = &Subnet->Options; } Error = MemOptInit( &Option, Entry->OptionId, Entry->InfoSize, Entry->Info ); if( NO_ERROR != Error ) return Error; Error = MemOptClassAddOption( OptClass, Option, UserId, VendorId, &DelOpt, INVALID_UNIQ_ID );
ASSERT( NULL == DelOpt ); if( NO_ERROR != Error ) MemFree( Option );
return Error;
case DBCFG_SCOPE: //
// IpAddress = Address, Mask = Mask, SubType = State,
// Flags = Policy
//
Error = MemSubnetInit( &Subnet, Entry->IpAddress, Entry->Mask, Entry->SubType, SScopeId, Entry->Name, Entry->Comment ); if( NO_ERROR != Error ) return Error;
Error = MemServerAddSubnet( Server, Subnet, INVALID_UNIQ_ID ); if( NO_ERROR != Error ) MemSubnetCleanup( Subnet );
return Error; case DBCFG_MSCOPE : //
// MscopeId = MScopeId, Ttl = TTL, MscopeLang = LangTag,
// ExpiryTime = ExpiryTime, SubType = State, Flags =
// Policy..
//
Error = MemMScopeInit( &Subnet, Entry->MscopeId, Entry->SubType, Entry->Flags, (BYTE)Entry->Ttl, Entry->Name, Entry->Comment, Entry->MscopeLang, *(DATE_TIME *)&Entry->ExpiryTime ); if( NO_ERROR != Error ) return Error;
Error = MemServerAddMScope( Server, Subnet, INVALID_UNIQ_ID ); if( NO_ERROR != Error ) MemSubnetCleanup( Subnet );
Subnet->ServerPtr = Server; return Error;
case DBCFG_RANGE :
//
// RangeStart = Start, RangeEnd = End, RangeMask = Mask,
// Flags = State, BootpAllocated, BootpMax =
// MaxBootpAllowed... Also, IpAddress or MscopeId
//
if( Entry->Bitmasks & Bitmasks[DBCFG_IPADDRESS] ) { Error = MemServerGetUAddressInfo( Server, Entry->IpAddress, &Subnet, NULL, NULL, NULL ); } else { Error = MemServerFindMScope( Server, Entry->MscopeId, NULL, &Subnet ); } if( NO_ERROR != Error ) return Error;
return MemSubnetAddRange( Subnet, Entry->RangeStart, Entry->RangeEnd, Entry->Flags, Entry->BootpAllocated, Entry->BootpMax, &DelRange, INVALID_UNIQ_ID ); case DBCFG_EXCL: //
// RangeStart = Start, RangeEnd = End
//
if( Entry->Bitmasks & Bitmasks[DBCFG_IPADDRESS] ) { Error = MemServerGetUAddressInfo( Server, Entry->IpAddress, &Subnet, NULL, NULL, NULL ); } else { Error = MemServerFindMScope( Server, Entry->MscopeId, NULL, &Subnet ); } if( NO_ERROR != Error ) return Error;
return MemSubnetAddExcl( Subnet, Entry->RangeStart, Entry->RangeEnd, &DelExcl, INVALID_UNIQ_ID );
case DBCFG_RESERVATION : //
// IpAddress = Address, Flags = Flags, Info = ClientUID
//
Error = MemServerGetAddressInfo( Server, Entry->IpAddress, &Subnet, NULL, NULL, NULL ); if( NO_ERROR != Error ) return Error;
return MemReserveAdd( &Subnet->Reservations, Entry->IpAddress, Entry->Flags, Entry->Info, Entry->InfoSize, INVALID_UNIQ_ID ); default:
return ERROR_INTERNAL_ERROR; } }
DWORD AddDbEntryEx( IN PM_SERVER Server, IN PDBCFG_ENTRY Entry ) { DWORD Error; LPSTR EntryTypes[] = { "Class", "Opt", "OptDef", "Scope", "Mscope", "Range", "Excl", "Reservation", "Unknown1", "Unknown2", "Unknown3" }; Error = AddDbEntry( Server, Entry ); if( NO_ERROR != Error ) { Tr("Error adding entry[%ld] %s: 0x%lx\n", Entry->Index, EntryTypes[Entry->Type], Error ); }
return Error; }
DWORD ReadDbEntries( IN OUT LPBYTE *Mem, IN OUT ULONG *MemSize, IN OUT PM_SERVER *Server ) { DBCFG_ENTRY Entry; DWORD Error = NO_ERROR;
Error = MemServerInit( Server, -1, 0, 0, NULL, NULL ); if( NO_ERROR != Error ) return Error; while( Error == NO_ERROR ) {
Error = ReadDbEntryEx( Mem, MemSize, &Entry ); if( NO_ERROR != Error ) { Tr( "ReadDbEntryEx: %ld\n", Error ); break; }
if( Entry.Type == DBCFG_END ) { Error = NO_ERROR; break; }
Error = AddDbEntryEx( *Server, &Entry ); if( NULL != Entry.Buf ) LocalFree( Entry.Buf ); if( NO_ERROR != Error ) { Tr( "AddDbEntryEx: %ld\n", Error ); return Error; } }
Tr("ReadDbEntries: %ld\n", Error);
if( NO_ERROR != Error ) { MemServerFree( *Server ); (*Server) = NULL; } return Error; }
|