559 lines
18 KiB
C
559 lines
18 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1997-1998 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
rtmmain.h
|
||
|
|
||
|
Abstract:
|
||
|
Private defs for Routing Table Manager DLL
|
||
|
|
||
|
Author:
|
||
|
Chaitanya Kodeboyina (chaitk) 17-Aug-1998
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#ifndef __ROUTING_RTMMAIN_H__
|
||
|
#define __ROUTING_RTMMAIN_H__
|
||
|
|
||
|
//
|
||
|
// Common Header for all RTM internal structures
|
||
|
//
|
||
|
|
||
|
// Disable warnings for unnamed structs
|
||
|
#pragma warning(disable : 4201)
|
||
|
|
||
|
typedef struct _OBJECT_HEADER
|
||
|
{
|
||
|
#if DBG_HDL
|
||
|
union
|
||
|
{
|
||
|
DWORD TypeSign; // Type & unique signature for object
|
||
|
struct
|
||
|
{
|
||
|
CHAR Type; // Identifies type of the object
|
||
|
CHAR Signature[2]; // Pattern unique for an object type
|
||
|
CHAR Alloc; // Set + if allocated, - if freed
|
||
|
};
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
#if DBG_MEM
|
||
|
LIST_ENTRY AllocLE; // On list of all memory allocations
|
||
|
#endif
|
||
|
|
||
|
LONG RefCount; // Reference count for this object
|
||
|
|
||
|
#if DBG_REF
|
||
|
LONG RefTypes[MAX_REFS]; // Nature of references on the object
|
||
|
#endif
|
||
|
}
|
||
|
OBJECT_HEADER, *POBJECT_HEADER;
|
||
|
|
||
|
#pragma warning(default : 4201)
|
||
|
|
||
|
|
||
|
//
|
||
|
// Defns to validate handles & convert them to pointers
|
||
|
//
|
||
|
|
||
|
#define HANDLE_CONV_KEY \
|
||
|
(ULONG_PTR)(('RTM2') | ('RTM2' << (sizeof(PVOID) - 4)))
|
||
|
|
||
|
#define MAKE_HANDLE_FROM_POINTER(ObjectHandle) \
|
||
|
(HANDLE) (((ULONG_PTR) ObjectHandle) ^ HANDLE_CONV_KEY)
|
||
|
|
||
|
#define GET_POINTER_FROM_HANDLE(ObjectHandle) \
|
||
|
(PVOID) (((ULONG_PTR) ObjectHandle) ^ HANDLE_CONV_KEY)
|
||
|
|
||
|
|
||
|
PVOID
|
||
|
__inline
|
||
|
GetObjectFromHandle(HANDLE ObjectHandle, UCHAR ObjectType)
|
||
|
{
|
||
|
POBJECT_HEADER ObjHdr = GET_POINTER_FROM_HANDLE(ObjectHandle);
|
||
|
|
||
|
UNREFERENCED_PARAMETER(ObjectType);
|
||
|
|
||
|
#if DBG_HDL
|
||
|
try
|
||
|
{
|
||
|
if (ObjHdr->TypeSign != OBJECT_SIGNATURE[ObjectType])
|
||
|
{
|
||
|
if (ObjectType != GENERIC_TYPE)
|
||
|
{
|
||
|
ObjHdr = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
except(EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
ObjHdr = NULL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return ObjHdr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#define OBJECT_FROM_HANDLE(ObjectHandle, ObjectType) \
|
||
|
(POBJECT_HEADER) GetObjectFromHandle(ObjectHandle, ObjectType);
|
||
|
|
||
|
#define VALIDATE_OBJECT_HANDLE(ObjectHandle, ObjectType, pObject) \
|
||
|
*pObject = (PVOID) OBJECT_FROM_HANDLE(ObjectHandle, ObjectType);\
|
||
|
if ((!*pObject)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
|
||
|
#define ENTITY_FROM_HANDLE(EntityHandle) \
|
||
|
(PENTITY_INFO) GetObjectFromHandle(EntityHandle, ENTITY_TYPE)
|
||
|
|
||
|
#define VALIDATE_ENTITY_HANDLE(EntityHandle, pEntity) \
|
||
|
*pEntity = ENTITY_FROM_HANDLE(EntityHandle); \
|
||
|
if ((!*pEntity)||((*pEntity)->State==ENTITY_STATE_DEREGISTERED))\
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
#define DBG_VALIDATE_ENTITY_HANDLE(EntityHandle, pEntity) \
|
||
|
UNREFERENCED_PARAMETER(EntityHandle); \
|
||
|
DBG_UNREFERENCED_LOCAL_VARIABLE(*pEntity); \
|
||
|
if (DBG_HDL) \
|
||
|
{ \
|
||
|
VALIDATE_ENTITY_HANDLE(EntityHandle, pEntity) \
|
||
|
}
|
||
|
|
||
|
|
||
|
#define DEST_FROM_HANDLE(DestHandle) \
|
||
|
(PDEST_INFO) GetObjectFromHandle(DestHandle, DEST_TYPE)
|
||
|
|
||
|
#define VALIDATE_DEST_HANDLE(DestHandle, pDest) \
|
||
|
*pDest = DEST_FROM_HANDLE(DestHandle); \
|
||
|
if ((!(*pDest)) || ((*pDest)->State == DEST_STATE_DELETED)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
|
||
|
#define ROUTE_FROM_HANDLE(RouteHandle) \
|
||
|
(PROUTE_INFO) GetObjectFromHandle(RouteHandle, ROUTE_TYPE)
|
||
|
|
||
|
#define VALIDATE_ROUTE_HANDLE(RouteHandle, pRoute) \
|
||
|
*pRoute = ROUTE_FROM_HANDLE(RouteHandle); \
|
||
|
if ( \
|
||
|
(!(*pRoute)) || \
|
||
|
((*pRoute)->RouteInfo.State == RTM_ROUTE_STATE_DELETED) \
|
||
|
) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
|
||
|
#define NEXTHOP_FROM_HANDLE(NextHopHandle) \
|
||
|
(PNEXTHOP_INFO) GetObjectFromHandle(NextHopHandle, NEXTHOP_TYPE)
|
||
|
|
||
|
#define VALIDATE_NEXTHOP_HANDLE(NextHopHandle, pNextHop) \
|
||
|
*pNextHop = NEXTHOP_FROM_HANDLE(NextHopHandle); \
|
||
|
if (!(*pNextHop)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
|
||
|
#define DEST_ENUM_FROM_HANDLE(DestEnumHandle) \
|
||
|
(PDEST_ENUM) GetObjectFromHandle(DestEnumHandle, DEST_ENUM_TYPE)
|
||
|
|
||
|
#define VALIDATE_DEST_ENUM_HANDLE(DestEnumHandle, pDestEnum) \
|
||
|
*pDestEnum = DEST_ENUM_FROM_HANDLE(DestEnumHandle); \
|
||
|
if ((!*pDestEnum)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
|
||
|
#define ROUTE_ENUM_FROM_HANDLE(RouteEnumHandle) \
|
||
|
(PROUTE_ENUM) GetObjectFromHandle(RouteEnumHandle, ROUTE_ENUM_TYPE)
|
||
|
|
||
|
#define VALIDATE_ROUTE_ENUM_HANDLE(RouteEnumHandle, pRouteEnum) \
|
||
|
*pRouteEnum = ROUTE_ENUM_FROM_HANDLE(RouteEnumHandle); \
|
||
|
if ((!*pRouteEnum)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
#define NEXTHOP_ENUM_FROM_HANDLE(EnumHandle) \
|
||
|
(PNEXTHOP_ENUM) GetObjectFromHandle(EnumHandle, NEXTHOP_ENUM_TYPE)
|
||
|
|
||
|
#define VALIDATE_NEXTHOP_ENUM_HANDLE(NextHopEnumHandle, pNextHopEnum) \
|
||
|
*pNextHopEnum = NEXTHOP_ENUM_FROM_HANDLE(NextHopEnumHandle); \
|
||
|
if ((!*pNextHopEnum)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
|
||
|
#define NOTIFY_FROM_HANDLE(NotifyHandle) \
|
||
|
(PNOTIFY_INFO) GetObjectFromHandle(NotifyHandle, NOTIFY_TYPE)
|
||
|
|
||
|
#define VALIDATE_NOTIFY_HANDLE(NotifyHandle, pNotify) \
|
||
|
*pNotify = NOTIFY_FROM_HANDLE(NotifyHandle); \
|
||
|
if ((!*pNotify) || ((*pNotify)->CNIndex < 0)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
|
||
|
#define ROUTE_LIST_FROM_HANDLE(ListHandle) \
|
||
|
(PROUTE_LIST) GetObjectFromHandle(ListHandle, ROUTE_LIST_TYPE)
|
||
|
|
||
|
#define VALIDATE_ROUTE_LIST_HANDLE(ListHandle, pList) \
|
||
|
*pList = ROUTE_LIST_FROM_HANDLE(ListHandle); \
|
||
|
if ((!*pList)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
#define LIST_ENUM_FROM_HANDLE(ListEnumHandle) \
|
||
|
(PLIST_ENUM) GetObjectFromHandle(ListEnumHandle, LIST_ENUM_TYPE)
|
||
|
|
||
|
#define VALIDATE_LIST_ENUM_HANDLE(ListEnumHandle, pListEnum) \
|
||
|
*pListEnum = LIST_ENUM_FROM_HANDLE(ListEnumHandle); \
|
||
|
if ((!*pListEnum)) \
|
||
|
{ \
|
||
|
return ERROR_INVALID_HANDLE; \
|
||
|
} \
|
||
|
|
||
|
|
||
|
//
|
||
|
// Defns used to maintain reference count on structures
|
||
|
//
|
||
|
|
||
|
|
||
|
ULONG
|
||
|
__inline
|
||
|
InitializeObjectReference(POBJECT_HEADER Object, UCHAR RefType)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(RefType);
|
||
|
|
||
|
#if DBG_REF
|
||
|
InterlockedIncrement(&Object->RefTypes[RefType]);
|
||
|
#endif
|
||
|
|
||
|
return InterlockedIncrement(&Object->RefCount);
|
||
|
}
|
||
|
|
||
|
|
||
|
ULONG
|
||
|
__inline
|
||
|
ReferenceObject(POBJECT_HEADER Object, UCHAR RefType)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(RefType);
|
||
|
|
||
|
// Once ref falls to 0, this should never happen
|
||
|
ASSERT(Object->RefCount > 0);
|
||
|
|
||
|
#if DBG_REF
|
||
|
ASSERT(Object->RefTypes[RefType] >= 0);
|
||
|
|
||
|
InterlockedIncrement(&Object->RefTypes[RefType]);
|
||
|
#endif
|
||
|
|
||
|
return InterlockedIncrement(&Object->RefCount);
|
||
|
}
|
||
|
|
||
|
|
||
|
ULONG
|
||
|
__inline
|
||
|
DereferenceObject(POBJECT_HEADER Object, UCHAR RefType)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(RefType);
|
||
|
|
||
|
// Ref count should be +ve before we decrement it
|
||
|
ASSERT(Object->RefCount > 0);
|
||
|
|
||
|
#if DBG_REF
|
||
|
ASSERT(Object->RefTypes[RefType] > 0);
|
||
|
|
||
|
InterlockedDecrement(&Object->RefTypes[RefType]);
|
||
|
#endif
|
||
|
|
||
|
return InterlockedDecrement(&Object->RefCount);
|
||
|
}
|
||
|
|
||
|
|
||
|
#define INITIALIZE_INSTANCE_REFERENCE(Instance, RefType) \
|
||
|
InitializeObjectReference(&Instance->ObjectHeader, RefType);
|
||
|
|
||
|
#define REFERENCE_INSTANCE(Instance, RefType) \
|
||
|
ReferenceObject(&Instance->ObjectHeader, RefType);
|
||
|
|
||
|
#define DEREFERENCE_INSTANCE(Instance, RefType) \
|
||
|
if (DereferenceObject(&Instance->ObjectHeader, RefType) == 0) \
|
||
|
DestroyInstance(Instance);
|
||
|
|
||
|
|
||
|
#define INITIALIZE_ADDR_FAMILY_REFERENCE(Instance, RefType) \
|
||
|
InitializeObjectReference(&Instance->ObjectHeader, RefType);
|
||
|
|
||
|
#define REFERENCE_ADDR_FAMILY(AddrFamilyInfo, RefType) \
|
||
|
ReferenceObject(&AddrFamilyInfo->ObjectHeader, RefType);
|
||
|
|
||
|
#define DEREFERENCE_ADDR_FAMILY(AddrFamInfo, RefType) \
|
||
|
if (DereferenceObject(&AddrFamInfo->ObjectHeader,RefType) == 0) \
|
||
|
DestroyAddressFamily(AddrFamInfo);
|
||
|
|
||
|
|
||
|
#define INITIALIZE_ENTITY_REFERENCE(Entity, RefType) \
|
||
|
InitializeObjectReference(&Entity->ObjectHeader, RefType);
|
||
|
|
||
|
#define REFERENCE_ENTITY(Entity, RefType) \
|
||
|
ReferenceObject(&Entity->ObjectHeader, RefType);
|
||
|
|
||
|
#define DEREFERENCE_ENTITY(Entity, RefType) \
|
||
|
if (DereferenceObject(&Entity->ObjectHeader, RefType) == 0) \
|
||
|
DestroyEntity(Entity);
|
||
|
|
||
|
|
||
|
#define INITIALIZE_DEST_REFERENCE(Dest, RefType) \
|
||
|
InitializeObjectReference(&(Dest)->ObjectHeader, RefType);
|
||
|
|
||
|
#define REFERENCE_DEST(Dest, RefType) \
|
||
|
ReferenceObject(&(Dest)->ObjectHeader, RefType);
|
||
|
|
||
|
#define DEREFERENCE_DEST(Dest, RefType) \
|
||
|
if (DereferenceObject(&(Dest)->ObjectHeader, RefType) == 0) \
|
||
|
DestroyDest(Dest);
|
||
|
|
||
|
|
||
|
#define INITIALIZE_ROUTE_REFERENCE(Route, RefType) \
|
||
|
InitializeObjectReference(&(Route)->ObjectHeader, RefType);
|
||
|
|
||
|
#define REFERENCE_ROUTE(Route, RefType) \
|
||
|
ReferenceObject(&(Route)->ObjectHeader, RefType);
|
||
|
|
||
|
#define DEREFERENCE_ROUTE(Route, RefType) \
|
||
|
if (DereferenceObject(&(Route)->ObjectHeader, RefType) == 0) \
|
||
|
DestroyRoute(Route);
|
||
|
|
||
|
|
||
|
#define INITIALIZE_NEXTHOP_REFERENCE(NextHop, RefType) \
|
||
|
InitializeObjectReference(&(NextHop)->ObjectHeader, RefType);
|
||
|
|
||
|
#define REFERENCE_NEXTHOP(NextHop, RefType) \
|
||
|
ReferenceObject(&(NextHop)->ObjectHeader, RefType);
|
||
|
|
||
|
#define DEREFERENCE_NEXTHOP(NextHop, RefType) \
|
||
|
if (DereferenceObject(&(NextHop)->ObjectHeader, RefType) == 0) \
|
||
|
DestroyNextHop(NextHop);
|
||
|
|
||
|
//
|
||
|
// Macros used to lock structures using critical sections
|
||
|
//
|
||
|
|
||
|
#define CREATE_LOCK(Lock) \
|
||
|
InitializeCriticalSection((Lock))
|
||
|
|
||
|
#define DELETE_LOCK(Lock) \
|
||
|
DeleteCriticalSection((Lock))
|
||
|
|
||
|
#define ACQUIRE_LOCK(Lock) \
|
||
|
EnterCriticalSection((Lock))
|
||
|
|
||
|
#define RELEASE_LOCK(Lock) \
|
||
|
LeaveCriticalSection((Lock))
|
||
|
|
||
|
|
||
|
//
|
||
|
// Macros used to lock structures in read or write mode
|
||
|
//
|
||
|
|
||
|
typedef RTL_RESOURCE READ_WRITE_LOCK, *PREAD_WRITE_LOCK;
|
||
|
|
||
|
#define CREATE_READ_WRITE_LOCK(pRWL) \
|
||
|
RtlInitializeResource((pRWL))
|
||
|
|
||
|
#define DELETE_READ_WRITE_LOCK(pRWL) \
|
||
|
RtlDeleteResource((pRWL))
|
||
|
|
||
|
#define READ_WRITE_LOCK_CREATED(pRWL) (TRUE)
|
||
|
|
||
|
#define ACQUIRE_READ_LOCK(pRWL) \
|
||
|
RtlAcquireResourceShared((pRWL),TRUE)
|
||
|
|
||
|
#define RELEASE_READ_LOCK(pRWL) \
|
||
|
RtlReleaseResource((pRWL))
|
||
|
|
||
|
#define ACQUIRE_WRITE_LOCK(pRWL) \
|
||
|
RtlAcquireResourceExclusive((pRWL),TRUE)
|
||
|
|
||
|
#define RELEASE_WRITE_LOCK(pRWL) \
|
||
|
RtlReleaseResource((pRWL))
|
||
|
|
||
|
#define READ_LOCK_TO_WRITE_LOCK(pRWL) \
|
||
|
RtlConvertSharedToExclusive((pRWL))
|
||
|
|
||
|
#define WRITE_LOCK_TO_READ_LOCK(pRWL) \
|
||
|
RtlConvertExclusiveToShared((pRWL))
|
||
|
|
||
|
//
|
||
|
// Macros to acquire and release dynamic R/W locks
|
||
|
// [ This has been borrowed from the MGM libary ]
|
||
|
//
|
||
|
|
||
|
#define ACQUIRE_DYNAMIC_READ_LOCK(ppRWL) \
|
||
|
AcquireReadLock((PMGM_READ_WRITE_LOCK *)ppRWL)
|
||
|
|
||
|
#define RELEASE_DYNAMIC_READ_LOCK(ppRWL) \
|
||
|
ReleaseReadLock((PMGM_READ_WRITE_LOCK *)ppRWL)
|
||
|
|
||
|
#define ACQUIRE_DYNAMIC_WRITE_LOCK(ppRWL) \
|
||
|
AcquireWriteLock((PMGM_READ_WRITE_LOCK *)ppRWL)
|
||
|
|
||
|
#define RELEASE_DYNAMIC_WRITE_LOCK(ppRWL) \
|
||
|
ReleaseWriteLock((PMGM_READ_WRITE_LOCK *)ppRWL)
|
||
|
|
||
|
|
||
|
//
|
||
|
// Macros used in allocating and operating on memory
|
||
|
//
|
||
|
|
||
|
#define ZeroMemory RtlZeroMemory
|
||
|
#define CopyMemory RtlCopyMemory
|
||
|
#define CompareMemory RtlEqualMemory
|
||
|
|
||
|
#define AllocOnStack(nb) _alloca((nb))
|
||
|
|
||
|
#define AllocMemory(nb) HeapAlloc(RtmGlobals.GlobalHeap, \
|
||
|
0, \
|
||
|
(nb))
|
||
|
|
||
|
#define AllocNZeroMemory(nb) HeapAlloc(RtmGlobals.GlobalHeap, \
|
||
|
HEAP_ZERO_MEMORY, \
|
||
|
(nb))
|
||
|
|
||
|
#define FreeMemory(ptr) HeapFree(RtmGlobals.GlobalHeap, \
|
||
|
0, \
|
||
|
(ptr))
|
||
|
|
||
|
#if !DBG_MEM
|
||
|
|
||
|
#define AllocNZeroObject(nb) AllocNZeroMemory(nb)
|
||
|
|
||
|
#else
|
||
|
|
||
|
PVOID
|
||
|
__inline
|
||
|
AllocNZeroObject(UINT NumBytes)
|
||
|
{
|
||
|
OBJECT_HEADER *Object;
|
||
|
|
||
|
Object = AllocNZeroMemory(NumBytes);
|
||
|
|
||
|
if (Object)
|
||
|
{
|
||
|
|
||
|
ACQUIRE_ALLOCS_LIST_LOCK();
|
||
|
InsertTailList(&RtmGlobals.AllocsList, &Object->AllocLE);
|
||
|
RELEASE_ALLOCS_LIST_LOCK();
|
||
|
}
|
||
|
|
||
|
return Object;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#if !DBG_MEM
|
||
|
|
||
|
#define FreeObject(ptr) FreeMemory(ptr)
|
||
|
|
||
|
#else
|
||
|
|
||
|
VOID
|
||
|
__inline
|
||
|
FreeObject(PVOID Object)
|
||
|
{
|
||
|
ACQUIRE_ALLOCS_LIST_LOCK();
|
||
|
RemoveEntryList(&((POBJECT_HEADER)Object)->AllocLE);
|
||
|
RELEASE_ALLOCS_LIST_LOCK();
|
||
|
|
||
|
FreeMemory(Object);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Other Misc Macros
|
||
|
//
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
__inline
|
||
|
NumBitsInDword (DWORD Dword)
|
||
|
{
|
||
|
DWORD NumBits = 0;
|
||
|
|
||
|
while (Dword)
|
||
|
{
|
||
|
Dword &= (Dword - 1);
|
||
|
|
||
|
NumBits++;
|
||
|
}
|
||
|
|
||
|
return NumBits;
|
||
|
}
|
||
|
|
||
|
#define NUMBER_OF_BITS NumBitsInDword
|
||
|
|
||
|
//
|
||
|
// Error Handling and other related macros
|
||
|
//
|
||
|
#define SUCCESS(code) (code == NO_ERROR)
|
||
|
|
||
|
//
|
||
|
// DLL Startup, Cleanup Functions and Macros
|
||
|
//
|
||
|
|
||
|
BOOL
|
||
|
RtmDllStartup(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
RtmDllCleanup(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
DWORD
|
||
|
RtmApiStartup(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
#define CHECK_FOR_RTM_API_INITIALIZED() \
|
||
|
if (!RtmGlobals.ApiInitialized) \
|
||
|
{ \
|
||
|
Status = RtmApiStartup(); \
|
||
|
\
|
||
|
if (Status != NO_ERROR) \
|
||
|
{ \
|
||
|
return Status; \
|
||
|
} \
|
||
|
} \
|
||
|
|
||
|
#endif //__ROUTING_RTMMAIN_H__
|