1101 lines
37 KiB
C
1101 lines
37 KiB
C
/*++
|
|
|
|
Copyright (c) 1995-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rtutils.h
|
|
|
|
Abstract:
|
|
Public declarations for the Router process utility functions.
|
|
|
|
--*/
|
|
|
|
#ifndef __ROUTING_RTUTILS_H__
|
|
#pragma option push -b -a8 -pc -A- /*P_O_Push*/
|
|
#define __ROUTING_RTUTILS_H__
|
|
|
|
#if _MSC_VER > 1000
|
|
#pragma once
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// TRACING FUNCTION PROTOTYPES //
|
|
// //
|
|
// See DOCUMENT for more information //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Definitions for flags and constants //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define TRACE_USE_FILE 0x00000001
|
|
#define TRACE_USE_CONSOLE 0x00000002
|
|
#define TRACE_NO_SYNCH 0x00000004
|
|
|
|
#define TRACE_NO_STDINFO 0x00000001
|
|
#define TRACE_USE_MASK 0x00000002
|
|
#define TRACE_USE_MSEC 0x00000004
|
|
|
|
#define INVALID_TRACEID 0xFFFFFFFF
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// ANSI entry-points //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceRegisterExA(
|
|
IN LPCSTR lpszCallerName,
|
|
IN DWORD dwFlags
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceDeregisterA(
|
|
IN DWORD dwTraceID
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceDeregisterExA(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceGetConsoleA(
|
|
IN DWORD dwTraceID,
|
|
OUT LPHANDLE lphConsole
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TracePrintfA(
|
|
IN DWORD dwTraceID,
|
|
IN LPCSTR lpszFormat,
|
|
IN ... OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TracePrintfExA(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPCSTR lpszFormat,
|
|
IN ... OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceVprintfExA(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPCSTR lpszFormat,
|
|
IN va_list arglist
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TracePutsExA(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPCSTR lpszString
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceDumpExA(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPBYTE lpbBytes,
|
|
IN DWORD dwByteCount,
|
|
IN DWORD dwGroupSize,
|
|
IN BOOL bAddressPrefix,
|
|
IN LPCSTR lpszPrefix
|
|
);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// ANSI entry-points macros //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define TraceRegisterA(a) TraceRegisterExA(a,0)
|
|
#define TraceVprintfA(a,b,c) TraceVprintfExA(a,0,b,c)
|
|
#define TracePutsA(a,b) TracePutsExA(a,0,b)
|
|
#define TraceDumpA(a,b,c,d,e,f) TraceDumpExA(a,0,b,c,d,e,f)
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Unicode entry-points //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceRegisterExW(
|
|
IN LPCWSTR lpszCallerName,
|
|
IN DWORD dwFlags
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceDeregisterW(
|
|
IN DWORD dwTraceID
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceDeregisterExW(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceGetConsoleW(
|
|
IN DWORD dwTraceID,
|
|
OUT LPHANDLE lphConsole
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TracePrintfW(
|
|
IN DWORD dwTraceID,
|
|
IN LPCWSTR lpszFormat,
|
|
IN ... OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TracePrintfExW(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPCWSTR lpszFormat,
|
|
IN ... OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceVprintfExW(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPCWSTR lpszFormat,
|
|
IN va_list arglist
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TracePutsExW(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPCWSTR lpszString
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
TraceDumpExW(
|
|
IN DWORD dwTraceID,
|
|
IN DWORD dwFlags,
|
|
IN LPBYTE lpbBytes,
|
|
IN DWORD dwByteCount,
|
|
IN DWORD dwGroupSize,
|
|
IN BOOL bAddressPrefix,
|
|
IN LPCWSTR lpszPrefix
|
|
);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Unicode entry-points macros //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define TraceRegisterW(a) TraceRegisterExW(a,0)
|
|
#define TraceVprintfW(a,b,c) TraceVprintfExW(a,0,b,c)
|
|
#define TracePutsW(a,b) TracePutsExW(a,0,b)
|
|
#define TraceDumpW(a,b,c,d,e,f) TraceDumpExW(a,0,b,c,d,e,f)
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Code-page dependent entry-point macros //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef UNICODE
|
|
#define TraceRegister TraceRegisterW
|
|
#define TraceDeregister TraceDeregisterW
|
|
#define TraceDeregisterEx TraceDeregisterExW
|
|
#define TraceGetConsole TraceGetConsoleW
|
|
#define TracePrintf TracePrintfW
|
|
#define TraceVprintf TraceVprintfW
|
|
#define TracePuts TracePutsW
|
|
#define TraceDump TraceDumpW
|
|
#define TraceRegisterEx TraceRegisterExW
|
|
#define TracePrintfEx TracePrintfExW
|
|
#define TraceVprintfEx TraceVprintfExW
|
|
#define TracePutsEx TracePutsExW
|
|
#define TraceDumpEx TraceDumpExW
|
|
#else
|
|
#define TraceRegister TraceRegisterA
|
|
#define TraceDeregister TraceDeregisterA
|
|
#define TraceDeregisterEx TraceDeregisterExA
|
|
#define TraceGetConsole TraceGetConsoleA
|
|
#define TracePrintf TracePrintfA
|
|
#define TraceVprintf TraceVprintfA
|
|
#define TracePuts TracePutsA
|
|
#define TraceDump TraceDumpA
|
|
#define TraceRegisterEx TraceRegisterExA
|
|
#define TracePrintfEx TracePrintfExA
|
|
#define TraceVprintfEx TraceVprintfExA
|
|
#define TracePutsEx TracePutsExA
|
|
#define TraceDumpEx TraceDumpExA
|
|
#endif
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// EVENT LOGGING FUNCTION PROTOTYPES //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// ANSI prototypes //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
VOID
|
|
APIENTRY
|
|
LogErrorA(
|
|
IN DWORD dwMessageId,
|
|
IN DWORD cNumberOfSubStrings,
|
|
IN LPSTR *plpwsSubStrings,
|
|
IN DWORD dwErrorCode
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
LogEventA(
|
|
IN DWORD wEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD cNumberOfSubStrings,
|
|
IN LPSTR *plpwsSubStrings
|
|
);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Unicode prototypes //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
LogErrorW(
|
|
IN DWORD dwMessageId,
|
|
IN DWORD cNumberOfSubStrings,
|
|
IN LPWSTR *plpwsSubStrings,
|
|
IN DWORD dwErrorCode
|
|
);
|
|
|
|
VOID
|
|
LogEventW(
|
|
IN DWORD wEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD cNumberOfSubStrings,
|
|
IN LPWSTR *plpwsSubStrings
|
|
);
|
|
|
|
|
|
#ifdef UNICODE
|
|
#define LogError LogErrorW
|
|
#define LogEvent LogEventW
|
|
#else
|
|
#define LogError LogErrorA
|
|
#define LogEvent LogEventA
|
|
#endif
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// The following functions allow the caller to specify the event source. //
|
|
// //
|
|
// Call RouterLogRegister with the strings which would be passed to //
|
|
// RegisterEventSource; this returns a handle which can be passed //
|
|
// to the functions RouterLogEvent and RouterLogEventData. //
|
|
// //
|
|
// Call RouterLogDeregister to close the handle. //
|
|
// //
|
|
// Macros are provided for the different kinds of event log entrys: //
|
|
// RouterLogError logs an error (EVENTLOG_ERROR_TYPE) //
|
|
// RouterLogWarning logs a warning (EVENTLOG_WARNING_TYPE) //
|
|
// RouterLogInformation logs information (EVENTLOG_INFORMATION_TYPE) //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// ANSI prototypes //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
HANDLE
|
|
RouterLogRegisterA(
|
|
LPCSTR lpszSource
|
|
);
|
|
|
|
VOID
|
|
RouterLogDeregisterA(
|
|
HANDLE hLogHandle
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventA(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD dwSubStringCount,
|
|
IN LPSTR *plpszSubStringArray,
|
|
IN DWORD dwErrorCode
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventDataA(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD dwSubStringCount,
|
|
IN LPSTR *plpszSubStringArray,
|
|
IN DWORD dwDataBytes,
|
|
IN LPBYTE lpDataBytes
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventStringA(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD dwSubStringCount,
|
|
IN LPSTR *plpszSubStringArray,
|
|
IN DWORD dwErrorCode,
|
|
IN DWORD dwErrorIndex
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventExA(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwErrorCode,
|
|
IN DWORD dwMessageId,
|
|
IN LPCSTR ptszFormat,
|
|
...
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventValistExA(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwErrorCode,
|
|
IN DWORD dwMessageId,
|
|
IN LPCSTR ptszFormat,
|
|
IN va_list arglist
|
|
);
|
|
|
|
DWORD
|
|
RouterGetErrorStringA(
|
|
IN DWORD dwErrorCode,
|
|
OUT LPSTR * lplpszErrorString
|
|
);
|
|
|
|
#define RouterLogErrorA(h,msg,count,array,err) \
|
|
RouterLogEventA(h,EVENTLOG_ERROR_TYPE,msg,count,array,err)
|
|
#define RouterLogWarningA(h,msg,count,array,err) \
|
|
RouterLogEventA(h,EVENTLOG_WARNING_TYPE,msg,count,array,err)
|
|
#define RouterLogInformationA(h,msg,count,array,err) \
|
|
RouterLogEventA(h,EVENTLOG_INFORMATION_TYPE,msg,count,array,err)
|
|
|
|
#define RouterLogErrorDataA(h,msg,count,array,c,buf) \
|
|
RouterLogEventDataA(h,EVENTLOG_ERROR_TYPE,msg,count,array,c,buf)
|
|
#define RouterLogWarningDataA(h,msg,count,array,c,buf) \
|
|
RouterLogEventDataA(h,EVENTLOG_WARNING_TYPE,msg,count,array,c,buf)
|
|
#define RouterLogInformationDataA(h,msg,count,array,c,buf) \
|
|
RouterLogEventDataA(h,EVENTLOG_INFORMATION_TYPE,msg,count,array,c,buf)
|
|
|
|
#define RouterLogErrorStringA(h,msg,count,array,err,index) \
|
|
RouterLogEventStringA(h,EVENTLOG_ERROR_TYPE,msg,count,array, err,index)
|
|
#define RouterLogWarningStringA(h,msg,count,array,err,index) \
|
|
RouterLogEventStringA(h,EVENTLOG_WARNING_TYPE,msg,count,array,err,index)
|
|
#define RouterLogInformationStringA(h,msg,count,array, err,index) \
|
|
RouterLogEventStringA(h,EVENTLOG_INFORMATION_TYPE,msg,count,array,err,\
|
|
index)
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Unicode prototypes //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
HANDLE
|
|
RouterLogRegisterW(
|
|
LPCWSTR lpszSource
|
|
);
|
|
|
|
VOID
|
|
RouterLogDeregisterW(
|
|
HANDLE hLogHandle
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventW(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD dwSubStringCount,
|
|
IN LPWSTR *plpszSubStringArray,
|
|
IN DWORD dwErrorCode
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventDataW(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD dwSubStringCount,
|
|
IN LPWSTR *plpszSubStringArray,
|
|
IN DWORD dwDataBytes,
|
|
IN LPBYTE lpDataBytes
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventStringW(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwMessageId,
|
|
IN DWORD dwSubStringCount,
|
|
IN LPWSTR *plpszSubStringArray,
|
|
IN DWORD dwErrorCode,
|
|
IN DWORD dwErrorIndex
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventExW(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwErrorCode,
|
|
IN DWORD dwMessageId,
|
|
IN LPCWSTR ptszFormat,
|
|
...
|
|
);
|
|
|
|
VOID
|
|
RouterLogEventValistExW(
|
|
IN HANDLE hLogHandle,
|
|
IN DWORD dwEventType,
|
|
IN DWORD dwErrorCode,
|
|
IN DWORD dwMessageId,
|
|
IN LPCWSTR ptszFormat,
|
|
IN va_list arglist
|
|
);
|
|
|
|
DWORD
|
|
RouterGetErrorStringW(
|
|
IN DWORD dwErrorCode,
|
|
OUT LPWSTR * lplpwszErrorString
|
|
);
|
|
|
|
|
|
#define RouterLogErrorW(h,msg,count,array,err) \
|
|
RouterLogEventW(h,EVENTLOG_ERROR_TYPE,msg,count,array,err)
|
|
#define RouterLogWarningW(h,msg,count,array,err) \
|
|
RouterLogEventW(h,EVENTLOG_WARNING_TYPE,msg,count,array,err)
|
|
#define RouterLogInformationW(h,msg,count,array,err) \
|
|
RouterLogEventW(h,EVENTLOG_INFORMATION_TYPE,msg,count,array,err)
|
|
|
|
#define RouterLogErrorDataW(h,msg,count,array,c,buf) \
|
|
RouterLogEventDataW(h,EVENTLOG_ERROR_TYPE,msg,count,array,c,buf)
|
|
#define RouterLogWarningDataW(h,msg,count,array,c,buf) \
|
|
RouterLogEventDataW(h,EVENTLOG_WARNING_TYPE,msg,count,array,c,buf)
|
|
#define RouterLogInformationDataW(h,msg,count,array,c,buf) \
|
|
RouterLogEventDataW(h,EVENTLOG_INFORMATION_TYPE,msg,count,array,c,buf)
|
|
|
|
#define RouterLogErrorStringW(h,msg,count,array,err,index) \
|
|
RouterLogEventStringW(h,EVENTLOG_ERROR_TYPE,msg,count,array,err,index)
|
|
#define RouterLogWarningStringW(h,msg,count,array,err,index) \
|
|
RouterLogEventStringW(h,EVENTLOG_WARNING_TYPE,msg,count,array,err,index)
|
|
#define RouterLogInformationStringW(h,msg,count,array,err,index) \
|
|
RouterLogEventStringW(h,EVENTLOG_INFORMATION_TYPE,msg,count,array,err,\
|
|
index)
|
|
|
|
|
|
#ifdef UNICODE
|
|
#define RouterLogRegister RouterLogRegisterW
|
|
#define RouterLogDeregister RouterLogDeregisterW
|
|
#define RouterLogEvent RouterLogEventW
|
|
#define RouterLogError RouterLogErrorW
|
|
#define RouterLogWarning RouterLogWarningW
|
|
#define RouterLogInformation RouterLogInformationW
|
|
#define RouterLogEventData RouterLogEventDataW
|
|
#define RouterLogErrorData RouterLogErrorDataW
|
|
#define RouterLogWarningData RouterLogWarningDataW
|
|
#define RouterLogInformationData RouterLogInformationDataW
|
|
#define RouterLogEventString RouterLogEventStringW
|
|
#define RouterLogEventEx RouterLogEventExW
|
|
#define RouterLogEventValistEx RouterLogEventValistExW
|
|
#define RouterLogErrorString RouterLogErrorStringW
|
|
#define RouterLogWarningString RouterLogWarningStringW
|
|
#define RouterLogInformationString RouterLogInformationStringW
|
|
#define RouterGetErrorString RouterGetErrorStringW
|
|
#
|
|
#else
|
|
#define RouterLogRegister RouterLogRegisterA
|
|
#define RouterLogDeregister RouterLogDeregisterA
|
|
#define RouterLogEvent RouterLogEventA
|
|
#define RouterLogError RouterLogErrorA
|
|
#define RouterLogWarning RouterLogWarningA
|
|
#define RouterLogInformation RouterLogInformationA
|
|
#define RouterLogEventData RouterLogEventDataA
|
|
#define RouterLogErrorData RouterLogErrorDataA
|
|
#define RouterLogWarningData RouterLogWarningDataA
|
|
#define RouterLogInformationData RouterLogInformationDataA
|
|
#define RouterLogEventString RouterLogEventStringA
|
|
#define RouterLogEventEx RouterLogEventExA
|
|
#define RouterLogEventValistEx RouterLogEventValistExA
|
|
#define RouterLogErrorString RouterLogErrorStringA
|
|
#define RouterLogWarningString RouterLogWarningStringA
|
|
#define RouterLogInformationString RouterLogInformationStringA
|
|
#define RouterGetErrorString RouterGetErrorStringA
|
|
#endif
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// WORKER THREAD POOL FUNCTIONS //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// definition of worker function passed in QueueWorkItem API //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef VOID (APIENTRY * WORKERFUNCTION)(PVOID);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Function: Queues the supplied work item in the work queue. //
|
|
// //
|
|
// functionptr: function to be called must be of WORKERFUNCTION type //
|
|
// context: opaque ptr //
|
|
// serviceinalertablethread: if TRUE gets scheduled in //
|
|
// a alertably waiting thread that never dies //
|
|
// Returns: 0 (success) //
|
|
// Win32 error codes for cases like out of memory //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
APIENTRY
|
|
QueueWorkItem(
|
|
IN WORKERFUNCTION functionptr,
|
|
IN PVOID context,
|
|
IN BOOL serviceinalertablethread
|
|
);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Function: Associates file handle with the completion port (all //
|
|
// asynchronous i/o on this handle will be queued to //
|
|
// the completion port) //
|
|
// //
|
|
// FileHandle: File handle to be associated with completion port //
|
|
// //
|
|
// CompletionProc: Procedure to be called when io associated with the file //
|
|
// handle completes. This function will be executed in //
|
|
// the context of non-alertable worker thread //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
APIENTRY
|
|
SetIoCompletionProc (
|
|
IN HANDLE FileHandle,
|
|
IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionProc
|
|
);
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// The following defines are included here as a hint on how the worker //
|
|
// thread pool is managed: //
|
|
// //
|
|
// There are NUM_ALERTABLE_THREADS permanent threads that never quit and //
|
|
// wait alertably on a alertable worker queue. These threads should solely //
|
|
// be used for work items that intiate asyncronous operation (file io, //
|
|
// waitable timer) that ABSOLUTELY require APCs to complete (preferable //
|
|
// method for IO is the usage of completio port API) //
|
|
// //
|
|
// There is a pool of the threads that wait on completion port //
|
|
// that used both for processing of IO and non-IO related work items //
|
|
// //
|
|
// The minimum number of threads is Number of processors //
|
|
// The maximum number of threads is MAX_WORKER_THREADS //
|
|
// //
|
|
// A new thread is created if worker queue has not been served for more //
|
|
// that WORK_QUEUE_TIMEOUT //
|
|
// The existing thread will be shut down if it is not used for more than //
|
|
// THREAD_IDLE_TIMEOUT //
|
|
// //
|
|
// Note that worker threads age guaranteed to be alive for at least //
|
|
// THREAD_IDLE_TIMEOUT after the last work item is executed. This timeout //
|
|
// is chosen such that bulk of IO request could be completed before it //
|
|
// expires. If it is not enough for your case, use alertable thread with //
|
|
// APC, or create your own thread. //
|
|
// //
|
|
// Note: changing these flags will not change anything. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Number of alertable threads //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define NUM_ALERTABLE_THREADS 2
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Max number of threads at any time //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define MAX_WORKER_THREADS 10
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Time that the worker queue is not served before starting new thread //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define WORK_QUEUE_TIMEOUT 1 //sec
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Time that thread has to be idle before exiting //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define THREAD_IDLE_TIMEOUT 10 //sec
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// ROUTER ASSERT DECLARATION //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
RouterAssert(
|
|
IN PSTR pszFailedAssertion,
|
|
IN PSTR pszFileName,
|
|
IN DWORD dwLineNumber,
|
|
IN PSTR pszMessage OPTIONAL
|
|
);
|
|
|
|
|
|
#if DBG
|
|
#define RTASSERT(exp) \
|
|
if (!(exp)) \
|
|
RouterAssert(#exp, __FILE__, __LINE__, NULL)
|
|
#define RTASSERTMSG(msg, exp) \
|
|
if (!(exp)) \
|
|
RouterAssert(#exp, __FILE__, __LINE__, msg)
|
|
#else
|
|
#define RTASSERT(exp)
|
|
#define RTASSERTMSG(msg, exp)
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// REGISTRY CONFIGURATION FUNCTIONS //
|
|
// //
|
|
// The following definitions are used to read configuration information //
|
|
// about installed protocols. //
|
|
// //
|
|
// Call 'MprSetupProtocolEnum' to enumerate the routing-protocols //
|
|
// for transport 'dwTransportId'. This fills an array with entries //
|
|
// of type 'MPR_PROTOCOL_0'. //
|
|
// //
|
|
// The array loaded can be destroyed by calling 'MprSetupProtocolFree'. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define MAX_PROTOCOL_NAME_LEN 40
|
|
#define MAX_PROTOCOL_DLL_LEN 48
|
|
|
|
typedef struct _MPR_PROTOCOL_0 {
|
|
|
|
DWORD dwProtocolId; // e.g. IP_RIP
|
|
WCHAR wszProtocol[MAX_PROTOCOL_NAME_LEN+1]; // e.g. "IPRIP"
|
|
WCHAR wszDLLName[MAX_PROTOCOL_DLL_LEN+1]; // e.g. "iprip2.dll"
|
|
|
|
} MPR_PROTOCOL_0;
|
|
|
|
|
|
DWORD APIENTRY
|
|
MprSetupProtocolEnum(
|
|
IN DWORD dwTransportId,
|
|
OUT LPBYTE* lplpBuffer, // MPR_PROTOCOL_0
|
|
OUT LPDWORD lpdwEntriesRead
|
|
);
|
|
|
|
|
|
DWORD APIENTRY
|
|
MprSetupProtocolFree(
|
|
IN LPVOID lpBuffer
|
|
);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Extensions to Rtutils to improve worker thread utilization. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define ROUTING_RESERVED
|
|
#define OPT1_1
|
|
#define OPT1_2
|
|
#define OPT2_1
|
|
#define OPT2_2
|
|
#define OPT3_1
|
|
#define OPT3_2
|
|
|
|
|
|
//
|
|
// When everyone is migrated to using Winsock2
|
|
//
|
|
|
|
#if 0
|
|
|
|
|
|
//==========================================================================================================//
|
|
//==========================================================================================================//
|
|
|
|
// ASYNC_SOCKET_DATA structure is used to pass / receive back data from an //
|
|
// asynchronous wait recv from call //
|
|
|
|
typedef struct _ASYNC_SOCKET_DATA {
|
|
OVERLAPPED Overlapped; // reserved. not to be used
|
|
IN WSABUF WsaBuf; // WsaBuf.buf to be initialized to point to buffer
|
|
// WsaBuf.len set to the length of the buffer
|
|
OUT SOCKADDR_IN SrcAddress; // AsyncWsaRecvFrom fills this with the source address of the packet
|
|
OUT DWORD NumBytesReceived; // AsyncWsaRecvFrom fills this with the number of bytes returned in the packet
|
|
IN OUT DWORD Flags; // Used to set flags for WSARecvFrom, and returns the flags set by WSARecvFrom
|
|
OUT DWORD Status; // status returned by IO Completion Port
|
|
|
|
IN WORKERFUNCTION pFunction; // Function to be executed on receiving packet
|
|
IN PVOID pContext; // context for the above function
|
|
} ASYNC_SOCKET_DATA, *PASYNC_SOCKET_DATA;
|
|
|
|
|
|
|
|
// AsyncSocketInit() binds the socket to the IOCompletionPort. This should be called//
|
|
// after the socket is created and before AsyncWsaRecvFrom() call is made //
|
|
DWORD
|
|
APIENTRY
|
|
AsyncSocketInit (
|
|
SOCKET sock
|
|
);
|
|
|
|
|
|
// This should be called only after the appropriate fields in SockData are initialized //
|
|
// This sets up an asynchronous WSARecvFrom(), and on its return dispatches the //
|
|
// function to a worker thread. It should be remembered that the function will run in //
|
|
// a worker thread which might later on be deleted. So SetWaitableTimer() and //
|
|
// asynchronous receive calls should be avoided unless you are sure that it would not be//
|
|
// a problem. It is adviced that if you want the function to run in an alertable thread,//
|
|
// then have the callback function queue a work item to alertable thread. Queue work //
|
|
// items to alertable worker threads for SetWaitableTimer() and async receives. //
|
|
// One must not make many AsyncWSArecvFrom() calls, as the buffer are non-paged //
|
|
DWORD
|
|
APIENTRY
|
|
AsyncWSARecvFrom (
|
|
SOCKET sock,
|
|
PASYNC_SOCKET_DATA pSockData
|
|
);
|
|
|
|
#endif // all winsock2 functions
|
|
|
|
//==========================================================================================================//
|
|
//==========================================================================================================//
|
|
|
|
|
|
// forward declarations
|
|
struct _WAIT_THREAD_ENTRY;
|
|
struct _WT_EVENT_ENTRY;
|
|
|
|
|
|
typedef struct _WT_TIMER_ENTRY {
|
|
LONGLONG te_Timeout;
|
|
|
|
WORKERFUNCTION te_Function;
|
|
PVOID te_Context;
|
|
DWORD te_ContextSz;
|
|
BOOL te_RunInServer;
|
|
|
|
DWORD te_Status;
|
|
|
|
#define TIMER_INACTIVE 3
|
|
#define TIMER_ACTIVE 4
|
|
|
|
DWORD te_ServerId;
|
|
struct _WAIT_THREAD_ENTRY *teP_wte;
|
|
LIST_ENTRY te_ServerLinks;
|
|
|
|
LIST_ENTRY te_Links;
|
|
|
|
BOOL te_Flag; //todo: not used
|
|
DWORD te_TimerId;
|
|
} WT_TIMER_ENTRY, *PWT_TIMER_ENTRY;
|
|
|
|
|
|
typedef struct _WT_WORK_ITEM {
|
|
WORKERFUNCTION wi_Function; // function to call
|
|
PVOID wi_Context; // context passed into function call
|
|
DWORD wi_ContextSz; // size of context, used for allocating
|
|
BOOL wi_RunInServer; // run in wait server thread or get queued to some worker thread
|
|
|
|
struct _WT_EVENT_ENTRY *wiP_ee;
|
|
LIST_ENTRY wi_ServerLinks;
|
|
LIST_ENTRY wi_Links; //todo not req // link to next and prev element
|
|
} WT_WORK_ITEM, *PWT_WORK_ITEM;
|
|
|
|
#define WT_EVENT_BINDING WT_WORK_ITEM
|
|
#define PWT_EVENT_BINDING PWT_WORK_ITEM
|
|
|
|
|
|
//
|
|
// WT_EVENT_ENTRY
|
|
//
|
|
typedef struct _WT_EVENT_ENTRY {
|
|
HANDLE ee_Event;
|
|
BOOL ee_bManualReset; // is the event manually reset
|
|
BOOL ee_bInitialState; // is the initial state of the event active
|
|
BOOL ee_bDeleteEvent; // was the event created as part of createWaitEvent
|
|
|
|
DWORD ee_Status; // current status of the event entry
|
|
BOOL ee_bHighPriority;
|
|
|
|
LIST_ENTRY eeL_wi;
|
|
|
|
BOOL ee_bSignalSingle; // signal single function or multiple functions // how many functions to activate when event signalled (default:1)
|
|
BOOL ee_bOwnerSelf; // the owner if the client which create this event
|
|
|
|
INT ee_ArrayIndex; // index in the events array if active
|
|
|
|
DWORD ee_ServerId; // Id of server: used while deleting
|
|
struct _WAIT_THREAD_ENTRY *eeP_wte; // pointer to wait thread entry
|
|
LIST_ENTRY ee_ServerLinks; // used by wait server thread
|
|
LIST_ENTRY ee_Links; // used by client
|
|
|
|
DWORD ee_RefCount;
|
|
BOOL ee_bFlag; //todo: notused // reserved for use during deletion
|
|
DWORD ee_EventId; //todo: remove it, being used only for testing/debugging
|
|
|
|
} WT_EVENT_ENTRY, *PWT_EVENT_ENTRY;
|
|
|
|
|
|
|
|
|
|
// PROTOTYPES OF FUNCTIONS USED IN THIS FILE ONLY
|
|
//
|
|
|
|
|
|
// used by client to create a wait event
|
|
// context size should be 0 if you are passing a dword instead of a pointer
|
|
// if pEvent field is set, then lpName and security attributes are ignored
|
|
// if pFunction is NULL, then pContext, dwContextSz, and bRunInServerContext are ignored
|
|
PWT_EVENT_ENTRY
|
|
APIENTRY
|
|
CreateWaitEvent (
|
|
//IN PWT_EVENT_ENTRY pEventEntry, // handle to event entry if initialized by others
|
|
IN HANDLE pEvent OPT1_1, // handle to event if already created
|
|
|
|
IN LPSECURITY_ATTRIBUTES lpEventAttributes OPT1_2, // pointer to security attributes
|
|
IN BOOL bManualReset,
|
|
IN BOOL bInitialState,
|
|
IN LPCTSTR lpName OPT1_2, // pointer to event-object name
|
|
|
|
IN BOOL bHighPriority, // create high priority event
|
|
|
|
IN WORKERFUNCTION pFunction OPT2_1, // if null, means will be set by other clients
|
|
IN PVOID pContext OPT2_1, // can be null
|
|
IN DWORD dwContextSz OPT2_1, // size of context: used for allocating context to functions
|
|
IN BOOL bRunInServerContext OPT2_1 // run in server thread or get dispatched to worker thread
|
|
);
|
|
|
|
|
|
|
|
//dwContextSz should be 0 if a dword is being passed. >0 only if pointer to block of that size is being passed.
|
|
PWT_EVENT_BINDING
|
|
APIENTRY
|
|
CreateWaitEventBinding (
|
|
IN PWT_EVENT_ENTRY pee,
|
|
IN WORKERFUNCTION pFunction,
|
|
IN PVOID pContext,
|
|
IN DWORD dwContextSz,
|
|
IN BOOL bRunInServerContext
|
|
);
|
|
|
|
|
|
PWT_TIMER_ENTRY
|
|
APIENTRY
|
|
CreateWaitTimer (
|
|
IN WORKERFUNCTION pFunction,
|
|
IN PVOID pContext,
|
|
IN DWORD dwContextSz,
|
|
IN BOOL bRunInServerContext
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
DeRegisterWaitEventBindingSelf (
|
|
IN PWT_EVENT_BINDING pwiWorkItem
|
|
);
|
|
|
|
|
|
DWORD
|
|
APIENTRY
|
|
DeRegisterWaitEventBinding (
|
|
IN PWT_EVENT_BINDING pwiWorkItem
|
|
);
|
|
|
|
|
|
//all the events and timers should be registered with one waitThread server
|
|
//todo: change the above requirement
|
|
DWORD
|
|
APIENTRY
|
|
DeRegisterWaitEventsTimers (
|
|
PLIST_ENTRY pLEvents, // list of events linked by ee_Links field
|
|
PLIST_ENTRY pLTimers // list of timers linked by te_Links field:
|
|
//these lists can be a single list entry, or a multiple entry list with a list header entry.
|
|
);
|
|
|
|
// this should be used only when called within a server thread
|
|
DWORD
|
|
APIENTRY
|
|
DeRegisterWaitEventsTimersSelf (
|
|
IN PLIST_ENTRY pLEvents,
|
|
IN PLIST_ENTRY pLTimers
|
|
);
|
|
|
|
|
|
DWORD
|
|
APIENTRY
|
|
RegisterWaitEventBinding (
|
|
IN PWT_EVENT_BINDING pwiWorkItem
|
|
);
|
|
|
|
// Register the client with the wait thread
|
|
DWORD
|
|
APIENTRY
|
|
RegisterWaitEventsTimers (
|
|
IN PLIST_ENTRY pLEventsToAdd,
|
|
IN PLIST_ENTRY pLTimersToAdd
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
UpdateWaitTimer (
|
|
IN PWT_TIMER_ENTRY pte,
|
|
IN LONGLONG *time
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
WTFree (
|
|
PVOID ptr
|
|
);
|
|
|
|
|
|
//used to free wait-event. Should be deallocated using DeRegisterWaitEventsTimers
|
|
//This function is to be used only when the events have not been registered
|
|
VOID
|
|
APIENTRY
|
|
WTFreeEvent (
|
|
IN PWT_EVENT_ENTRY peeEvent
|
|
);
|
|
|
|
|
|
//used to free wait-timer. Should be deallocated using DeRegisterWaitEventsTimers
|
|
//This function is to be used only when the timers have not been registered
|
|
VOID
|
|
APIENTRY
|
|
WTFreeTimer (
|
|
IN PWT_TIMER_ENTRY pteTimer
|
|
);
|
|
|
|
|
|
VOID
|
|
APIENTRY
|
|
DebugPrintWaitWorkerThreads (
|
|
DWORD dwDebugLevel
|
|
);
|
|
|
|
#define DEBUGPRINT_FILTER_NONCLIENT_EVENTS 0x2
|
|
#define DEBUGPRINT_FILTER_EVENTS 0x4
|
|
#define DEBUGPRINT_FILTER_TIMERS 0x8
|
|
|
|
|
|
//
|
|
//ERROR VALUES
|
|
//
|
|
#define ERROR_WAIT_THREAD_UNAVAILABLE 1
|
|
|
|
#define ERROR_WT_EVENT_ALREADY_DELETED 2
|
|
|
|
|
|
|
|
|
|
#define TIMER_HIGH(time) \
|
|
(((LARGE_INTEGER*)&time)->HighPart)
|
|
|
|
#define TIMER_LOW(time) \
|
|
(((LARGE_INTEGER*)&time)->LowPart)
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#pragma option pop /*P_O_Pop*/
|
|
#endif // ___ROUTING_RTUTILS_H__
|
|
|
|
|