windows-nt/Source/XPSP1/NT/sdktools/pdh/inc/pdhidef.h

846 lines
19 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
pdhidef.h
Abstract:
function definitions used internally by the performance data helper
functions
--*/
#ifndef _PDHI_DEFS_H_
#define _PDHI_DEFS_H_
#pragma warning ( disable : 4115 )
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _DEBUG_MUTEXES
#define _DEBUG_MUTEXES 0 // for debugging
#endif
//#define _SHOW_PDH_MEM_ALLOCS 1
//#define _VALIDATE_PDH_MEM_ALLOCS 1
#include <locale.h>
#include "pdhitype.h" // required for data type definitions
//#include "pdhmsg.h" // error message definitions
//#include "strings.h" // for string constants
#if DBG
VOID
__cdecl
PdhDebugPrint(
ULONG DebugPrintLevel,
char* DebugMessage,
...
);
#define DebugPrint(x) PdhDebugPrint x
#else
#define DebugPrint(x)
#endif
#define STATIC_PDH_FUNCTION PDH_STATUS __stdcall
#define STATIC_BOOL BOOL __stdcall
#define STATIC_DWORD DWORD __stdcall
#define PDH_PLA_MUTEX L"__PDH_PLA_MUTEX__"
// global variable declarations
extern HANDLE ThisDLLHandle;
extern WCHAR szStaticLocalMachineName[];
extern HANDLE hPdhDataMutex;
extern HANDLE hPdhContextMutex;
extern HANDLE hPdhPlaMutex;
extern HANDLE hPdhHeap;
extern HANDLE hEventLog;
extern LONGLONG llRemoteRetryTime;
extern BOOL bEnableRemotePdhAccess;
extern DWORD dwPdhiLocalDefaultDataSource;
extern LONG dwCurrentRealTimeDataSource;
extern BOOL bProcessIsDetaching;
#ifndef _SHOW_PDH_MEM_ALLOCS
#define G_ALLOC(s) HeapAlloc (hPdhHeap, (HEAP_ZERO_MEMORY), s)
#define G_REALLOC(h,s) HeapReAlloc (hPdhHeap, (HEAP_ZERO_MEMORY), h, s)
#define G_FREE(h) if (h != NULL) HeapFree (hPdhHeap, 0, h)
#define G_SIZE(h) HeapSize (hPdhHeap, 0, h)
#else
#ifdef _VALIDATE_PDH_MEM_ALLOCS
__inline
LPVOID
PdhiHeapAlloc(DWORD s)
{
LPVOID lpRetVal;
HeapValidate(hPdhHeap, 0, NULL);
lpRetVal = HeapAlloc (hPdhHeap, HEAP_ZERO_MEMORY, s);
return lpRetVal;
}
__inline
LPVOID
PdhiHeapReAlloc(LPVOID h, DWORD s)
{
LPVOID lpRetVal;
HeapValidate(hPdhHeap, 0, NULL);
lpRetVal = HeapReAlloc (hPdhHeap, HEAP_ZERO_MEMORY, h, s);
return lpRetVal;
}
__inline
BOOL
PdhiHeapFree(LPVOID h)
{
BOOL bRetVal;
if (h == NULL) return TRUE;
HeapValidate(hPdhHeap, 0, NULL);
bRetVal = HeapFree (hPdhHeap, 0, h);
return bRetVal;
}
#define G_ALLOC(s) PdhiHeapAlloc (s)
#define G_REALLOC(h,s) PdhiHeapReAlloc (h, s)
#define G_FREE(h) PdhiHeapFree (h)
#define G_SIZE(h) HeapSize (hPdhHeap, 0, h)
#else
__inline
LPVOID
PdhiHeapAlloc(LPSTR szSourceFileName, DWORD dwLineNo, SIZE_T s)
{
LPVOID lpRetVal;
lpRetVal = HeapAlloc(hPdhHeap, HEAP_ZERO_MEMORY, s);
#ifdef _WIN64
DebugPrint((1, "G_ALLOC(%s#%d)(%I64d,0x%08X)\n",
szSourceFileName, dwLineNo,
(lpRetVal != NULL ? s : 0),
lpRetVal));
#else
DebugPrint((1, "G_ALLOC(%s#%d)(%d,0x%08X)\n",
szSourceFileName, dwLineNo,
(lpRetVal != NULL ? s : 0),
lpRetVal));
#endif
return lpRetVal;
}
__inline
LPVOID
PdhiHeapReAlloc(LPSTR szSourceFileName, DWORD dwLineNo, LPVOID h, SIZE_T s)
{
LPVOID lpRetVal;
SIZE_T dwBeforeSize;
DWORD dwCurrentThread = GetCurrentThreadId();
dwBeforeSize = HeapSize (hPdhHeap, 0, h);
lpRetVal = HeapReAlloc (hPdhHeap, HEAP_ZERO_MEMORY, h, s);
#ifdef _WIN64
DebugPrint((1, "G_REALLOC(%s#%d)(0x%08X,%I64d)(0x%08X,%I64d)\n",
szSourceFileName, dwLineNo,
h, dwBeforeSize,
lpRetVal, (lpRetVal != NULL ? s : 0)));
#else
DebugPrint((1, "G_REALLOC(%s#%d)(0x%08X,%d)(0x%08X,%d)\n",
szSourceFileName, dwLineNo,
h, dwBeforeSize,
lpRetVal, (lpRetVal != NULL ? s : 0)));
#endif
return lpRetVal;
}
__inline
BOOL
PdhiHeapFree(LPSTR szSourceFileName, DWORD dwLineNo, LPVOID h)
{
BOOL bRetVal;
SIZE_T dwBlockSize;
if (h == NULL) return TRUE;
dwBlockSize = HeapSize (hPdhHeap, 0, h);
bRetVal = HeapFree (hPdhHeap, 0, h);
#ifdef _WIN64
DebugPrint((1, "G_FREE(%s#%d)(0x%08X,%I64d)\n",
szSourceFileName, dwLineNo,
h,
(bRetVal ? dwBlockSize : 0)));
#else
DebugPrint((1, "G_FREE(%s#%d)(0x%08X,%d)\n",
szSourceFileName, dwLineNo,
h,
(bRetVal ? dwBlockSize : 0)));
#endif
return bRetVal;
}
#define G_ALLOC(s) PdhiHeapAlloc (__FILE__, __LINE__, s)
#define G_REALLOC(h,s) PdhiHeapReAlloc (__FILE__, __LINE__, h, s)
#define G_FREE(h) PdhiHeapFree (__FILE__, __LINE__, h)
#define G_SIZE(h) HeapSize (hPdhHeap, 0, h)
#endif
#endif
// (assumes dword is 4 bytes)
#define ALIGN_ON_DWORD(x) ((VOID *)(((DWORD_PTR)(x) & 3) ? (((DWORD_PTR)(x) & ~3) + 4 ) : ((DWORD_PTR)(x))))
#define DWORD_MULTIPLE(x) ((((x)+sizeof(DWORD)-1)/sizeof(DWORD))*sizeof(DWORD))
#define CLEAR_FIRST_FOUR_BYTES(x) *(DWORD *)(x) = 0L
// (assumes QuadWORD is 8 bytes)
#define ALIGN_ON_QWORD(x) ((VOID *)(((DWORD_PTR)(x) & 7) ? (((DWORD_PTR)(x) & ~7) + 8) : ((DWORD_PTR)(x))))
#define QWORD_MULTIPLE(x) ((((x)+sizeof(LONGLONG)-1)/sizeof(LONGLONG))*sizeof(LONGLONG))
#define CLEAR_FIRST_EIGHT_BYTES(x) *(LONGLONG *)(x) = 0L
#if _DEBUG_MUTEXES
__inline
DWORD
PdhiLocalWaitForMutex (
LPCSTR szSourceFileName,
DWORD dwLineNo,
HANDLE hMutex
)
{
DWORD dwReturnValue = PDH_INVALID_PARAMETER;
if (hMutex != NULL) {
FILETIME ft;
GetSystemTimeAsFileTime (&ft);
dwReturnValue = WaitForSingleObject (hMutex, 60000);
DebugPrint ((4, "\n[%8.8x] Mutex [%8.8x] %s by (%d) at: %s (%d)",
ft.dwLowDateTime,
(DWORD)hMutex,
(dwReturnValue == 0 ? "Locked" : "Lock Failed"),
GetCurrentThreadId(),
szSourceFileName, dwLineNo));
} else {
DebugPrint((4, "\nLock of NULL Mutex attmpted at: %s (%d)",
szSourceFileName, dwLineNo));
dwReturnValue = PDH_INVALID_PARAMETER;
}
return dwReturnValue;
}
#define WAIT_FOR_AND_LOCK_MUTEX(h) PdhiLocalWaitForMutex (__FILE__, __LINE__, h);
__inline
void
PdhiLocalReleaseMutex (
LPCSTR szSourceFileName,
DWORD dwLineNo,
HANDLE hMutex
)
{
BOOL bSuccess;
LONG lPrevCount = 0;
FILETIME ft;
if (hMutex != NULL) {
GetSystemTimeAsFileTime (&ft);
bSuccess = ReleaseMutex (hMutex);
DebugPrint((4, "\n[%8.8x] Mutex [%8.8x] %s by (%d) at: %s (%d)",
ft.dwLowDateTime,
(DWORD)hMutex,
(bSuccess ? "Released" : "Release Failed"),
GetCurrentThreadId(),
szSourceFileName, dwLineNo));
} else {
DebugPrint((4, "\nRelease of NULL Mutex attempted at: %s (%d)",
szSourceFileName, dwLineNo));
}
}
#define RELEASE_MUTEX(h) PdhiLocalReleaseMutex (__FILE__, __LINE__, h);
#else
#define WAIT_FOR_AND_LOCK_MUTEX(h) (h != NULL ? WaitForSingleObject(h, 60000) : WAIT_TIMEOUT)
#define RELEASE_MUTEX(h) (h != NULL ? ReleaseMutex(h) : FALSE)
#endif
#define LODWORD(ll) ((DWORD)((LONGLONG)ll & 0x00000000FFFFFFFF))
#define HIDWORD(ll) ((DWORD)(((LONGLONG)ll >> 32) & 0x00000000FFFFFFFF))
#define MAKELONGLONG(low, high) \
((LONGLONG) (((DWORD) (low)) | ((LONGLONG) ((DWORD) (high))) << 32))
#define SMALL_BUFFER_SIZE 4096
#define MEDIUM_BUFFER_SIZE 16834
#define LARGE_BUFFER_SIZE 65536
// set this to 1 to report code errors (i.e. debugging information)
// to the event log.
#define PDHI_REPORT_CODE_ERRORS 0
// set this to 1 to report user errors (i.e. things the normal user
// would care about) to the event log.
#define PDHI_REPORT_USER_ERRORS 1
// USER category errors are typically configuration, schema or access
// access errors, errors the user can usually do something about
#define PDH_EVENT_CATEGORY_USER 100
// COUNTER category errors are errors returned do to valid data returning
// invalid results. These are a special subset of USER Category errors.
#define PDH_EVENT_CATEGORY_COUNTER 110
// DEBUG category errors are of interest only to PDH developers as they
// indicate problems that can normally only be fixed by modifying the
// program code.
#define PDH_EVENT_CATEGORY_DEBUG 200
#define REPORT_EVENT(t,c,id) ReportEvent (hEventLog, t, c, id, NULL, 0, 0, NULL, NULL)
__inline
BOOL
CounterIsOkToUse ( void *pCounterArg )
{
PPDHI_COUNTER pCounter = (PPDHI_COUNTER)pCounterArg;
if (pCounter != NULL) {
if (pCounter->dwFlags & PDHIC_COUNTER_UNUSABLE) {
return FALSE;
} else {
return TRUE;
}
} else {
return FALSE;
}
}
DWORD
DataSourceTypeH (
IN HLOG hDataSource
);
DWORD
DataSourceTypeW (
IN LPCWSTR szDataSource
);
DWORD
DataSourceTypeA (
IN LPCSTR szDataSource
);
LPWSTR
GetStringResource (
DWORD dwResId
);
//
// Log file entries
//
extern LPCSTR szTsvLogFileHeader;
extern LPCSTR szCsvLogFileHeader;
extern LPCSTR szBinLogFileHeader;
extern LPCSTR szTsvType;
extern LPCSTR szCsvType;
extern LPCSTR szBinaryType;
extern const DWORD dwFileHeaderLength;
extern const DWORD dwTypeLoc;
extern const DWORD dwVersionLoc;
extern const DWORD dwFieldLength;
DWORD
UnmapReadonlyMappedFile (
LPVOID pMemoryBase,
BOOL *bNeedToCloseHandles
);
PDH_FUNCTION
PdhiGetLogCounterInfo (
IN HLOG hLog,
IN PPDHI_COUNTER pCounter
);
PDH_FUNCTION
PdhiEnumLoggedMachines (
IN HLOG hDataSource,
IN LPVOID mszMachineList,
IN LPDWORD pcchBufferSize,
IN BOOL bUnicode
);
PDH_FUNCTION
PdhiEnumLoggedObjects (
IN HLOG hDataSource,
IN LPCWSTR szMachineName,
IN LPVOID mszObjectList,
IN LPDWORD pcchBufferSize,
IN DWORD dwDetailLevel,
IN BOOL bRefresh,
IN BOOL bUnicode
);
PDH_FUNCTION
PdhiEnumLoggedObjectItems (
IN HLOG hDataSource,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPVOID mszCounterList,
IN LPDWORD pdwCounterListLength,
IN LPVOID mszInstanceList,
IN LPDWORD pdwInstanceListLength,
IN DWORD dwDetailLevel,
IN DWORD dwFlags,
IN BOOL bUnicode
);
BOOL
PdhiDataSourceHasDetailLevelsH (
IN HLOG hDataSource
);
BOOL
PdhiDataSourceHasDetailLevels (
IN LPWSTR szDataSource
);
PDH_FUNCTION
PdhiGetMatchingLogRecord (
IN HLOG hLog,
IN LONGLONG *pStartTime,
IN LPDWORD pdwIndex
);
PDH_FUNCTION
PdhiGetCounterValueFromLogFile (
IN HLOG hLog,
IN DWORD dwIndex,
IN PDHI_COUNTER * pCounter
);
STATIC_PDH_FUNCTION
PdhiGetCounterInfo (
IN HCOUNTER hCounter,
IN BOOLEAN bRetrieveExplainText,
IN LPDWORD pdwBufferSize,
IN PPDH_COUNTER_INFO_W lpBuffer,
IN BOOL bUnicode
);
// log.c
BOOL
PdhiCloseAllLoggers();
ULONG HashCounter(
LPWSTR szCounterName
);
void
PdhiInitCounterHashTable(
IN PDHI_COUNTER_TABLE pTable
);
void
PdhiResetInstanceCount(
IN PDHI_COUNTER_TABLE pTable
);
PDH_FUNCTION
PdhiFindCounterInstList(
IN PDHI_COUNTER_TABLE pHeadList,
IN LPWSTR szCounter,
OUT PPDHI_INST_LIST * pInstList
);
PDH_FUNCTION
PdhiFindInstance(
IN PLIST_ENTRY pHeadInst,
IN LPWSTR szInstance,
IN BOOLEAN bUpdateCount,
OUT PPDHI_INSTANCE * pInstance
);
DWORD
AddStringToMultiSz(
IN LPVOID mszDest,
IN LPWSTR szSource,
IN BOOL bUnicodeDest
);
// query.c
PDH_FUNCTION
PdhiCollectQueryData (
IN PPDHI_QUERY pQuery,
IN LONGLONG *pllTimeStamp
);
BOOL
PdhiQueryCleanup (
);
PDH_FUNCTION
PdhiConvertUnicodeToAnsi(
IN UINT uCodePage,
IN LPWSTR wszSrc,
IN LPSTR aszDest,
IN LPDWORD pdwSize
);
// qutils.c
DWORD
WINAPI
PdhiAsyncTimerThreadProc (
LPVOID pArg
);
BOOL
IsValidQuery (
IN HQUERY hQuery
);
BOOL
IsValidCounter (
IN HCOUNTER hCounter
);
BOOL
InitCounter (
IN OUT PPDHI_COUNTER pCounter
);
BOOL
ParseFullPathNameW (
IN LPCWSTR szFullCounterPath,
IN OUT PDWORD pdwBufferLength,
IN OUT PPDHI_COUNTER_PATH pCounter,
IN BOOL bWbemSyntax
);
BOOL
ParseInstanceName (
IN LPCWSTR szInstanceString,
IN OUT LPWSTR szInstanceName,
IN OUT LPWSTR szParentName,
IN OUT LPDWORD lpIndex
);
BOOL
FreeCounter (
IN PPDHI_COUNTER pThisCounter
);
BOOL
InitPerflibCounterInfo (
IN OUT PPDHI_COUNTER pCounter
);
BOOL
AddMachineToQueryLists (
IN PPERF_MACHINE pMachine,
IN PPDHI_COUNTER pNewCounter
);
BOOL
UpdateRealTimeCounterValue (
IN PPDHI_COUNTER pCounter
);
BOOL
UpdateRealTimeMultiInstanceCounterValue (
IN PPDHI_COUNTER pCounter
);
BOOL
UpdateCounterValue (
IN PPDHI_COUNTER pCounter,
IN PPERF_DATA_BLOCK pPerfData
);
BOOL
UpdateMultiInstanceCounterValue (
IN PPDHI_COUNTER pCounter,
IN PPERF_DATA_BLOCK pPerfData,
IN LONGLONG TimeStamp
);
BOOL
UpdateCounterObject(
IN PPDHI_COUNTER pCounter
);
#define GPCDP_GET_BASE_DATA 0x00000001
PVOID
GetPerfCounterDataPtr (
IN PPERF_DATA_BLOCK pPerfData,
IN PPDHI_COUNTER_PATH pPath,
IN PPERFLIB_COUNTER pplCtr,
IN DWORD dwFlags,
IN PPERF_OBJECT_TYPE *pPerfObject,
IN PDWORD pStatus
);
LONG
GetQueryPerfData (
IN PPDHI_QUERY pQuery,
IN LONGLONG *pTimeStamp
);
BOOL
GetInstanceByNameMatch (
IN PPERF_MACHINE pMachine,
IN OUT PPDHI_COUNTER pCounter
);
PDH_FUNCTION
PdhiResetLogBuffers (
IN HLOG hLog
);
DWORD
AddUniqueStringToMultiSz (
IN LPVOID mszDest,
IN LPSTR szSource,
IN BOOL bUnicodeDest
);
DWORD
AddUniqueWideStringToMultiSz (
IN LPVOID mszDest,
IN LPWSTR szSource,
IN BOOL bUnicodeDest
);
BOOL
PdhiBrowseDataSource (
IN HWND hWndParent,
IN LPVOID szFileName,
IN LPDWORD pcchFileNameSize,
IN BOOL bUnicodeString
);
LPWSTR
PdhiGetExplainText (
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPCWSTR szCounterName
);
LONG
GetCurrentServiceState (
SC_HANDLE hService,
BOOL * bStopped,
BOOL * bPaused
);
// wbem.cpp
BOOL
IsWbemDataSource (
IN LPCWSTR szDataSource
);
PDH_FUNCTION
PdhiFreeAllWbemServers (
);
PDH_FUNCTION
PdhiGetWbemExplainText (
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPCWSTR szCounterName,
IN LPWSTR szExplain,
IN LPDWORD pdwExplain
);
PDH_FUNCTION
PdhiEnumWbemMachines (
IN LPVOID pMachineList,
IN LPDWORD pcchBufferSize,
IN BOOL bUnicode
);
PDH_FUNCTION
PdhiEnumWbemObjects (
IN LPCWSTR szWideMachineName,
IN LPVOID mszObjectList,
IN LPDWORD pcchBufferSize,
IN DWORD dwDetailLevel,
IN BOOL bRefresh,
IN BOOL bUnicode
);
PDH_FUNCTION
PdhiGetDefaultWbemObject (
IN LPCWSTR szMachineName,
IN LPVOID szDefaultObjectName,
IN LPDWORD pcchBufferSize,
IN BOOL bUnicode
);
PDH_FUNCTION
PdhiEnumWbemObjectItems (
IN LPCWSTR szWideMachineName,
IN LPCWSTR szWideObjectName,
IN LPVOID mszCounterList,
IN LPDWORD pcchCounterListLength,
IN LPVOID mszInstanceList,
IN LPDWORD pcchInstanceListLength,
IN DWORD dwDetailLevel,
IN DWORD dwFlags,
IN BOOL bUnicode
);
PDH_FUNCTION
PdhiGetDefaultWbemProperty (
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPVOID szDefaultCounterName,
IN LPDWORD pcchBufferSize,
IN BOOL bUnicode
);
PDH_FUNCTION
PdhiEncodeWbemPathW (
IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements,
IN LPWSTR szFullPathBuffer,
IN LPDWORD pcchBufferSize,
IN LANGID LangId,
IN DWORD dwFlags
);
PDH_FUNCTION
PdhiDecodeWbemPathA (
IN LPCSTR szFullPathBuffer,
IN PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements,
IN LPDWORD pcchBufferSize,
IN LANGID LangId,
IN DWORD dwFlags
);
PDH_FUNCTION
PdhiDecodeWbemPathW (
IN LPCWSTR szFullPathBuffer,
IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements,
IN LPDWORD pcchBufferSize,
IN LANGID LangId,
IN DWORD dwFlags
);
PDH_FUNCTION
PdhiEncodeWbemPathA (
PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements,
LPSTR szFullPathBuffer,
LPDWORD pcchBufferSize,
LANGID LangId,
DWORD dwFlags
);
BOOL
WbemInitCounter (
IN PPDHI_COUNTER pCounter
);
LONG
GetQueryWbemData (
IN PPDHI_QUERY pQuery,
IN LONGLONG *pllTimeStamp
);
PDH_FUNCTION
PdhiCloseWbemCounter (
PPDHI_COUNTER pCounter
);
PDH_FUNCTION
PdhiFreeWbemQuery (
PPDHI_QUERY pThisQuery
);
// Doubly-linked list manipulation routines. Implemented as macros
// but logically these are procedures.
//
#define InitializeListHead(ListHead) (\
(ListHead)->Flink = (ListHead)->Blink = (ListHead))
#define IsListEmpty(ListHead) \
((ListHead)->Flink == (ListHead))
#define RemoveHeadList(ListHead) \
(ListHead)->Flink;\
{RemoveEntryList((ListHead)->Flink)}
#define RemoveTailList(ListHead) \
(ListHead)->Blink;\
{RemoveEntryList((ListHead)->Blink)}
#define RemoveEntryList(Entry) {\
PLIST_ENTRY _EX_Blink;\
PLIST_ENTRY _EX_Flink;\
_EX_Flink = (Entry)->Flink;\
_EX_Blink = (Entry)->Blink;\
_EX_Blink->Flink = _EX_Flink;\
_EX_Flink->Blink = _EX_Blink;\
}
#define InsertTailList(ListHead,Entry) {\
PLIST_ENTRY _EX_Blink;\
PLIST_ENTRY _EX_ListHead;\
_EX_ListHead = (ListHead);\
_EX_Blink = _EX_ListHead->Blink;\
(Entry)->Flink = _EX_ListHead;\
(Entry)->Blink = _EX_Blink;\
_EX_Blink->Flink = (Entry);\
_EX_ListHead->Blink = (Entry);\
}
#define InsertHeadList(ListHead,Entry) {\
PLIST_ENTRY _EX_Flink;\
PLIST_ENTRY _EX_ListHead;\
_EX_ListHead = (ListHead);\
_EX_Flink = _EX_ListHead->Flink;\
(Entry)->Flink = _EX_Flink;\
(Entry)->Blink = _EX_ListHead;\
_EX_Flink->Blink = (Entry);\
_EX_ListHead->Flink = (Entry);\
}
#define PopEntryList(ListHead) \
(ListHead)->Next;\
{\
PSINGLE_LIST_ENTRY FirstEntry;\
FirstEntry = (ListHead)->Next;\
if (FirstEntry != NULL) { \
(ListHead)->Next = FirstEntry->Next;\
} \
}
#define PushEntryList(ListHead,Entry) \
(Entry)->Next = (ListHead)->Next; \
(ListHead)->Next = (Entry)
#ifdef __cplusplus
}
#endif
#endif // _PDHI_DEFS_H_