windows-nt/Source/XPSP1/NT/net/dhcp/server/mm/classdefl.c
2020-09-26 16:20:57 +08:00

294 lines
8.4 KiB
C

//================================================================================
// Copyright (C) 1997 Microsoft Corporation
// Author: RameshV
// Description: implements the basic structures for a list of class defintitions
// ThreadSafe: no
// Locks: none
// Please read stdinfo.txt for programming style.
//================================================================================
#include <mm.h>
#include <array.h>
#include <wchar.h>
//BeginExport(typedef)
typedef struct _M_CLASSDEF {
DWORD RefCount;
DWORD ClassId;
BOOL IsVendor;
DWORD Type;
LPWSTR Name;
LPWSTR Comment;
DWORD nBytes;
LPBYTE ActualBytes;
} M_CLASSDEF, *PM_CLASSDEF, *LPM_CLASSDEF;
typedef struct _M_CLASSDEFLIST {
ARRAY ClassDefArray;
} M_CLASSDEFLIST, *PM_CLASSDEFLIST, *LPM_CLASSDEFLIST;
//EndExport(typedef)
//BeginExport(inline)
DWORD _inline
MemClassDefListInit(
IN OUT PM_CLASSDEFLIST ClassDefList
) {
return MemArrayInit(&ClassDefList->ClassDefArray);
}
//EndExport(inline)
//BeginExport(inline)
DWORD _inline
MemClassDefListCleanup(
IN OUT PM_CLASSDEFLIST ClassDefList
) {
return MemArrayCleanup(&ClassDefList->ClassDefArray);
}
//EndExport(inline)
//BeginExport(function)
DWORD
MemClassDefListFindClassDefInternal( // dont use this fn outside of classdefl.c
IN PM_CLASSDEFLIST ClassDefList,
IN DWORD ClassId,
IN LPWSTR Name,
IN LPBYTE ActualBytes,
IN DWORD nBytes,
IN LPBOOL pIsVendor,
OUT PARRAY_LOCATION Location
) //EndExport(function)
{
DWORD Error;
PM_CLASSDEF ThisClassDef;
for( Error = MemArrayInitLoc(&ClassDefList->ClassDefArray, Location)
; ERROR_FILE_NOT_FOUND != Error ;
Error = MemArrayNextLoc(&ClassDefList->ClassDefArray, Location)
) {
Require(ERROR_SUCCESS == Error);
Error = MemArrayGetElement(
&ClassDefList->ClassDefArray,
Location,
(LPVOID *)&ThisClassDef
);
Require(ERROR_SUCCESS == Error && ThisClassDef);
if( pIsVendor != NULL && ThisClassDef->IsVendor != *pIsVendor)
continue;
if( ThisClassDef->ClassId == ClassId ) {
return ERROR_SUCCESS;
}
if( nBytes == ThisClassDef->nBytes ) {
if( 0 == memcmp(ActualBytes, ThisClassDef->ActualBytes, nBytes)) {
return ERROR_SUCCESS;
}
}
if( Name && 0 == wcscmp(ThisClassDef->Name, Name) ) {
return ERROR_SUCCESS;
}
}
return ERROR_FILE_NOT_FOUND;
}
//BeginExport(inline)
DWORD _inline
MemClassDefListFindOptDef( // search either by ClassId or by Actual bytes and fill matched stuff
IN PM_CLASSDEFLIST ClassDefList,
IN DWORD ClassId,
IN LPWSTR Name,
IN LPBYTE ActualBytes,
IN DWORD nBytes,
OUT PM_CLASSDEF *ClassDef // NULL or valid matching class def
) {
ARRAY_LOCATION Location;
DWORD Error;
AssertRet(ClassDef, ERROR_INVALID_PARAMETER);
Error = MemClassDefListFindClassDefInternal(
ClassDefList,
ClassId,
Name,
ActualBytes,
nBytes,
NULL,
&Location
);
if( ERROR_SUCCESS != Error) return Error;
Error = MemArrayGetElement(
&ClassDefList->ClassDefArray,
&Location,
(LPVOID*)ClassDef
);
Require(ERROR_SUCCESS == Error);
return Error;
}
//BeginExport(function)
DWORD
MemClassDefListAddClassDef( // Add or replace option
IN OUT PM_CLASSDEFLIST ClassDefList,
IN DWORD ClassId,
IN BOOL IsVendor,
IN DWORD Type,
IN LPWSTR Name,
IN LPWSTR Comment,
IN LPBYTE ActualBytes,
IN DWORD nBytes
) //EndExport(function)
{
ARRAY_LOCATION Location;
DWORD Error;
DWORD Size;
PM_CLASSDEF ThisClassDef;
PM_CLASSDEF OldClassDef;
AssertRet(ClassDefList && ClassId && Name && ActualBytes && nBytes, ERROR_INVALID_PARAMETER );
Error = MemClassDefListFindClassDefInternal(
ClassDefList,
ClassId,
Name,
ActualBytes,
nBytes,
&IsVendor,
&Location
);
Size = sizeof(M_CLASSDEF)+nBytes;
Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
Size += (1+wcslen(Name))*sizeof(WCHAR);
if( Comment ) Size += (1+wcslen(Comment))*sizeof(WCHAR);
ThisClassDef = MemAlloc(Size);
if( NULL == ThisClassDef ) return ERROR_NOT_ENOUGH_MEMORY;
ThisClassDef->RefCount = 1;
ThisClassDef->ClassId = ClassId;
ThisClassDef->IsVendor = IsVendor;
ThisClassDef->Type = Type;
ThisClassDef->nBytes = nBytes;
ThisClassDef->ActualBytes = sizeof(M_CLASSDEF) + (LPBYTE)ThisClassDef;
memcpy(ThisClassDef->ActualBytes, ActualBytes, nBytes);
ThisClassDef->Name = (LPWSTR)(ROUND_UP_COUNT(sizeof(M_CLASSDEF)+nBytes, ALIGN_WORST) + (LPBYTE)ThisClassDef);
wcscpy(ThisClassDef->Name, Name);
if( Comment ) {
ThisClassDef->Comment = 1 + wcslen(Name) + ThisClassDef->Name;
wcscpy(ThisClassDef->Comment, Comment);
} else {
ThisClassDef->Comment = NULL;
}
if( ERROR_SUCCESS == Error ) {
DebugPrint2("Overwriting class definition for class-id 0x%lx\n", ClassId);
Error = MemArrayGetElement(
&ClassDefList->ClassDefArray,
&Location,
(LPVOID *)&OldClassDef
);
Require(ERROR_SUCCESS == Error);
MemFree(OldClassDef);
Error = MemArraySetElement(
&ClassDefList->ClassDefArray,
&Location,
ThisClassDef
);
Require(ERROR_SUCCESS == Error);
return Error;
}
Error = MemArrayAddElement(
&ClassDefList->ClassDefArray,
ThisClassDef
);
if( ERROR_SUCCESS != Error ) MemFree(ThisClassDef);
return Error;
}
//BeginExport(inline)
DWORD _inline
MemClassDefListDelClassDef(
IN OUT PM_CLASSDEFLIST ClassDefList,
IN DWORD ClassId,
IN LPWSTR Name,
IN LPBYTE ActualBytes,
IN DWORD nBytes
) {
ARRAY_LOCATION Location;
DWORD Error;
PM_CLASSDEF ThisClassDef;
Error = MemClassDefListFindClassDefInternal(
ClassDefList,
ClassId,
Name,
ActualBytes,
nBytes,
NULL,
&Location
);
if( ERROR_SUCCESS != Error ) return Error;
Error = MemArrayDelElement(
&ClassDefList->ClassDefArray,
&Location,
&ThisClassDef
);
Require(ERROR_SUCCESS == Error && ThisClassDef);
MemFree(ThisClassDef);
return ERROR_SUCCESS;
}
//EndExport(inline)
//BeginExport(inline)
DWORD _inline
MemClassDefListGetRefCount(
IN PM_CLASSDEF ThisClassDef
) {
return ThisClassDef->RefCount;
}
//EndExport(inline)
//BeginExport(inline)
DWORD _inline
MemClassDefListIncRefCount( // return increased by one value
IN PM_CLASSDEF ThisClassDef
) {
return ++ThisClassDef->RefCount;
}
//EndExport(inline)
//BeginExport(inline)
DWORD _inline
MemClassDefListDecRefCount( // return decreased by one value
IN PM_CLASSDEF ThisClassDef
) {
return --ThisClassDef->RefCount;
}
//EndExport(inline)
ULONG ClassIdRunningCount = 100;
//BeginExport(function)
DWORD
MemNewClassId(
VOID
) //EndExport(function)
{
return InterlockedIncrement(&ClassIdRunningCount);
}
//================================================================================
// end of file
//================================================================================