Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

957 lines
25 KiB

#ifndef __h323ics_util_h
#define __h323ics_util_h
extern "C" DWORD DebugLevel;
EXTERN_C BOOL IsInList (LIST_ENTRY * ListHead, LIST_ENTRY * ListEntry);
EXTERN_C void ExtractList (LIST_ENTRY * DestinationListHead, LIST_ENTRY * SourceListHead);
EXTERN_C DWORD CountListLength (LIST_ENTRY * ListHead);
EXTERN_C void MergeLists (PLIST_ENTRY Result, PLIST_ENTRY Source);
EXTERN_C void AssertListIntegrity (LIST_ENTRY * ListHead);
#define INET_NTOA(a) inet_ntoa(*(struct in_addr*)&(a))
typedef HANDLE TIMER_HANDLE;
__inline
LPWSTR AnsiToUnicode (LPCSTR string, LPWSTR buffer, DWORD buffer_len)
{
int x;
x = MultiByteToWideChar (CP_ACP, 0, string, -1, buffer, buffer_len);
buffer [x] = 0;
return buffer;
}
__inline
LPSTR UnicodeToAnsi (LPCWSTR string, LPSTR buffer, DWORD buffer_len)
{
int x;
x = WideCharToMultiByte (CP_ACP, 0, string, -1, buffer, buffer_len,
NULL, FALSE);
buffer [x] = 0;
return buffer;
}
class TIMER_PROCESSOR;
class OVERLAPPED_PROCESSOR;
class Q931_INFO;
class SOURCE_Q931_INFO;
class DEST_Q931_INFO;
class LOGICAL_CHANNEL;
class H245_INFO;
class SOURCE_H245_INFO;
class DEST_H245_INFO;
class H323_STATE;
class SOURCE_H323_STATE;
class DEST_H323_STATE;
class CALL_BRIDGE;
#ifdef __cplusplus
template <class T>
inline BOOL BadReadPtr(T* p, DWORD dwSize = 1)
{
return IsBadReadPtr(p, dwSize * sizeof(T));
}
template <class T>
inline BOOL BadWritePtr(T* p, DWORD dwSize = 1)
{
return IsBadWritePtr(p, dwSize * sizeof(T));
}
#endif
#if defined(DBG)
void Debug (LPCTSTR);
void DebugF (LPCTSTR, ...);
void DebugError (DWORD, LPCTSTR);
void DebugErrorF (DWORD, LPCTSTR, ...);
void DebugLastError (LPCTSTR);
void DebugLastErrorF (LPCTSTR, ...);
void DumpMemory (const UCHAR * Data, ULONG Length);
void DumpError (DWORD);
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#ifdef __cplusplus
}
#endif // __cplusplus
#else // !defined(DBG)
static __inline void Debug (LPCTSTR) {}
static __inline void DebugF (LPCTSTR, ...) {}
static __inline void DebugError (DWORD, LPCTSTR) {}
static __inline void DebugErrorF (DWORD, LPCTSTR, ...) {}
static __inline void DebugLastError (LPCTSTR) {}
static __inline void DebugLastErrorF (LPCTSTR, ...) {}
static __inline void DumpMemory (const UCHAR * Data, ULONG Length) {}
static __inline void DumpError (DWORD) {}
#endif // defined(DBG)
#ifdef _ASSERTE
#undef _ASSERTE
#endif // _ASSERTE
#ifdef assert
#undef assert
#endif
#if DBG
// The latest and greatest Proxy assert
__inline void PxAssert(LPCTSTR file, DWORD line, LPCTSTR condition)
{
DebugF (_T("%s(%d) : Assertion failed, condition: %s\n"),
file, line, condition);
DebugBreak();
}
#define _ASSERTE(condition) if(condition);else\
{ PxAssert(_T(__FILE__), __LINE__, _T(#condition)); }
#define assert _ASSERTE
__inline void PxAssertNeverReached (LPCTSTR File, DWORD Line)
{
DebugF (_T("%s(%d) : Assertion failure, code path should never be executed\n"),
File, Line);
DebugBreak();
}
#define AssertNeverReached() PxAssertNeverReached (_T(__FILE__), __LINE__);
#else // !DBG
#define _ASSERTE(condition) NOP_FUNCTION
#define assert NOP_FUNCTION
#define AssertNeverReached() NOP_FUNCTION
#endif // DBG
// 0,1,2,3 : count of bytes from MSB to LSB in host order
#define BYTE0(l) ((BYTE)((DWORD)(l) >> 24))
#define BYTE1(l) ((BYTE)((DWORD)(l) >> 16))
#define BYTE2(l) ((BYTE)((DWORD)(l) >> 8))
#define BYTE3(l) ((BYTE)((DWORD)(l)))
// Handy macro to use in printf statements
#define BYTES0123(l) BYTE0(l), BYTE1(l), BYTE2(l), BYTE3(l)
// 0,1,2,3 : count of bytes from MSB to LSB in network order
#define NETORDER_BYTE0(l) ((BYTE)((BYTE *) &l)[0])
#define NETORDER_BYTE1(l) ((BYTE)((BYTE *) &l)[1])
#define NETORDER_BYTE2(l) ((BYTE)((BYTE *) &l)[2])
#define NETORDER_BYTE3(l) ((BYTE)((BYTE *) &l)[3])
#define SOCKADDR_IN_PRINTF(SocketAddress) \
ntohl ((SocketAddress) -> sin_addr.s_addr), \
ntohs ((SocketAddress) -> sin_port)
// Handy macro to use in printf statements
#define NETORDER_BYTES0123(l) NETORDER_BYTE0(l), NETORDER_BYTE1(l), \
NETORDER_BYTE2(l), NETORDER_BYTE3(l)
static __inline LONG RegQueryValueString (
IN HKEY Key,
IN LPCTSTR ValueName,
OUT LPTSTR ReturnString,
IN DWORD StringMax)
{
DWORD ValueLength;
DWORD Type;
LONG Status;
ValueLength = sizeof (TCHAR) * StringMax;
Status = RegQueryValueEx (Key, ValueName, NULL, &Type, (LPBYTE) ReturnString, &ValueLength);
if (Status != ERROR_SUCCESS)
return Status;
if (Type != REG_SZ)
return ERROR_INVALID_PARAMETER;
return ERROR_SUCCESS;
}
static __inline LONG RegQueryValueDWORD (
IN HKEY Key,
IN LPCTSTR ValueName,
OUT DWORD * ReturnValue)
{
DWORD ValueLength;
DWORD Type;
LONG Status;
ValueLength = sizeof (DWORD);
Status = RegQueryValueEx (Key, ValueName, NULL, &Type, (LPBYTE) ReturnValue, &ValueLength);
if (Status != ERROR_SUCCESS)
return Status;
if (Type != REG_DWORD)
return ERROR_INVALID_PARAMETER;
return ERROR_SUCCESS;
}
class SIMPLE_CRITICAL_SECTION_BASE
{
protected:
CRITICAL_SECTION CriticalSection;
protected:
void Lock (void) { EnterCriticalSection (&CriticalSection); }
void Unlock (void) { LeaveCriticalSection (&CriticalSection); }
void AssertLocked (void) { assert (PtrToUlong(CriticalSection.OwningThread) == GetCurrentThreadId()); }
void AssertNotLocked (void) { assert (!CriticalSection.OwningThread); }
void AssertThreadNotLocked (void) { assert (PtrToUlong(CriticalSection.OwningThread) != GetCurrentThreadId()); }
protected:
SIMPLE_CRITICAL_SECTION_BASE (void) {
InitializeCriticalSection (&CriticalSection);
}
~SIMPLE_CRITICAL_SECTION_BASE (void) {
if (CriticalSection.OwningThread) {
DebugF (_T("SIMPLE_CRITICAL_SECTION_BASE::~SIMPLE_CRITICAL_SECTION_BASE: thread %08XH stills holds this critical section (this %p)\n"),
PtrToUlong(CriticalSection.OwningThread), this);
}
AssertNotLocked();
DeleteCriticalSection (&CriticalSection);
}
};
#if ENABLE_REFERENCE_HISTORY
#include "dynarray.h"
#endif // ENABLE_REFERENCE_HISTORY
class SYNC_COUNTER;
class LIFETIME_CONTROLLER
{
#if ENABLE_REFERENCE_HISTORY
public:
LIST_ENTRY ListEntry;
struct REFERENCE_HISTORY {
LONG CurrentReferenceCount;
PVOID CallersAddress;
};
DYNAMIC_ARRAY <REFERENCE_HISTORY> ReferenceHistory;
CRITICAL_SECTION ReferenceHistoryLock;
#define MAKE_REFERENCE_HISTORY_ENTRY() { \
PVOID CallersAddress, CallersCallersAddress; \
RtlGetCallersAddress (&CallersAddress, &CallersCallersAddress); \
EnterCriticalSection (&ReferenceHistoryLock); \
REFERENCE_HISTORY * ReferenceHistoryNode = ReferenceHistory.AllocAtEnd (); \
ReferenceHistoryNode -> CallersAddress = CallersAddress; \
ReferenceHistoryNode -> CurrentReferenceCount = Count; \
LeaveCriticalSection (&ReferenceHistoryLock); \
}
#endif //ENABLE_REFERENCE_HISTORY
private:
LONG ReferenceCount;
SYNC_COUNTER * AssociatedSyncCounter;
protected:
LIFETIME_CONTROLLER (SYNC_COUNTER * AssocSyncCounter = NULL);
virtual ~LIFETIME_CONTROLLER ();
public:
void AddRef (void);
void Release (void);
};
template <DWORD SampleHistorySize>
class SAMPLE_PREDICTOR {
public:
SAMPLE_PREDICTOR (void) {
ZeroMemory ((PVOID) &Samples[0], sizeof (Samples));
FirstSampleIndex = 0;
SamplesArraySize = 0;
}
HRESULT AddSample (LONG Sample) {
DWORD ThisSampleIndex;
if (0UL == SampleHistorySize)
return E_ABORT;
if (SamplesArraySize < SampleHistorySize) {
ThisSampleIndex = SamplesArraySize;
SamplesArraySize++;
} else {
ThisSampleIndex = FirstSampleIndex; // Overwrite the least recent sample
FirstSampleIndex++;
FirstSampleIndex %= SampleHistorySize;
}
Samples [ThisSampleIndex] = Sample;
return S_OK;
}
LONG PredictNextSample (void) {
DWORD Index;
DWORD CurrentSampleIndex;
LONG Coefficient = 0;
LONG Prediction = 0;
if (0 == SampleHistorySize)
return 0;
for (Index = 0; Index < SamplesArraySize; Index++) {
if (0 == Index) {
Coefficient = (LONG)((SamplesArraySize & 1) << 1) - 1; // 1 or -1
} else {
Coefficient *= (LONG) Index - (LONG) SamplesArraySize - 1;
Coefficient /= (LONG) Index;
}
CurrentSampleIndex = (FirstSampleIndex + Index) % SamplesArraySize;
Prediction += Coefficient * Samples [CurrentSampleIndex];
}
return Prediction;
}
#if DBG
void PrintSamples (void) {
DWORD Index;
if (SamplesArraySize) {
DebugF (_T("Samples in predictor %p are: \n"), this);
for (Index = 0; Index < SamplesArraySize; Index++)
DebugF (_T("\t@%d(%d)-- %d\n"), Index, Index < FirstSampleIndex ? SamplesArraySize - (FirstSampleIndex - Index) : Index - FirstSampleIndex, Samples[Index]);
} else {
DebugF (_T("There are no samples in predictor %p.\n"), this);
}
}
#endif
HRESULT RetrieveOldSample (
IN DWORD StepsInThePast, // 0 -- most recent sample
OUT LONG * OldSample) {
DWORD SampleIndex;
if (0 == SampleHistorySize)
return E_ABORT;
if (StepsInThePast < SamplesArraySize) {
// Valid request
_ASSERTE (SamplesArraySize);
SampleIndex = (SamplesArraySize + FirstSampleIndex - StepsInThePast - 1) % SamplesArraySize;
*OldSample = Samples [SampleIndex];
return S_OK;
}
return ERROR_INVALID_DATA;
}
private:
LONG Samples [SampleHistorySize]; // This is where samples are kept
LONG PositiveTerms [SampleHistorySize];
LONG NegativeTerms [SampleHistorySize];
DWORD SamplesArraySize;
DWORD FirstSampleIndex; // Index of the least recent sample
};
static __inline HRESULT GetLastErrorAsResult (void) {
return GetLastError() == ERROR_SUCCESS ? S_OK : HRESULT_FROM_WIN32 (GetLastError());
}
static __inline HRESULT GetLastResult (void) {
return GetLastError() == ERROR_SUCCESS ? S_OK : HRESULT_FROM_WIN32 (GetLastError());
}
// A sync counter is an integer counter.
// It is kind of the opposite of a semaphore.
// When the counter is zero, the sync counter is signaled.
// When the counter is nonzero, the sync counter is not signaled.
class SYNC_COUNTER :
public SIMPLE_CRITICAL_SECTION_BASE
{
friend class LIFETIME_CONTROLLER;
private:
LONG CounterValue; // the current value of the counter
HANDLE ZeroEvent; // signaled when CounterValue = 0
public:
#if ENABLE_REFERENCE_HISTORY
LIST_ENTRY ActiveLifetimeControllers;
#endif // ENABLE_REFERENCE_HISTORY
SYNC_COUNTER ();
~SYNC_COUNTER ();
HRESULT Start (void);
void Stop (void);
void Increment (void);
void Decrement (void);
DWORD Wait (DWORD Timeout);
};
#define HRESULT_FROM_WIN32_ERROR_CODE HRESULT_FROM_WIN32
#define HRESULT_FROM_WINSOCK_ERROR_CODE HRESULT_FROM_WINSOCK_ERROR_CODE
// ASN.1 utility functions
// Setup_UUIE&
// SetupMember(
// IN H323_UserInformation *pH323UserInfo
// );
#define SetupMember(pH323UserInfo) \
(pH323UserInfo)->h323_uu_pdu.h323_message_body.u.setup
// Returns a non-zero value only. So don't try comparing it with TRUE/FALSE
// BOOL
// IsDestCallSignalAddressPresent(
// IN H323_UserInformation *pH323UserInfo
// );
#define IsDestCallSignalAddressPresent(pH323UserInfo) \
(SetupMember(pH323UserInfo).bit_mask & Setup_UUIE_destCallSignalAddress_present)
// Get the destCallSignalAddress member
// TransportAddress&
// DCSAddrMember(
// IN H323_UserInformation *pH323UserInfo
// );
#define DCSAddrMember(pH323UserInfo) \
SetupMember(pH323UserInfo).destCallSignalAddress
// Get the destCallSignalAddress member
// DESTINATION_ADDRESS *&
// DestAddrMember(
// IN H323_UserInformation *pH323UserInfo
// );
#define DestAddrMember(pH323UserInfo) \
SetupMember(pH323UserInfo).destinationAddress
// BOOL
// IsTransportAddressTypeIP(
// IN TransportAddress Addr
// );
#define IsTransportAddressTypeIP(Addr) \
(Addr.choice == ipAddress_chosen)
// BOOL
// IPAddrMember(
// IN TransportAddress Addr
// );
#define IPAddrMember(Addr) \
Addr.u.ipAddress
typedef struct Setup_UUIE_destinationAddress DESTINATION_ADDRESS;
///////////////////////////////////////////////////////////////////////////////
// //
// Routines for filling and extracting from structures used to //
// store Transport addresses in Q.931 and H.245 ASN //
// //
///////////////////////////////////////////////////////////////////////////////
// fills the TransportAddress port and address bytes with
// those specified. assumes that the passed in values are
// in host order
__inline void
FillTransportAddress(
IN DWORD IPv4Address, // host order
IN WORD Port, // host order
OUT TransportAddress &TransportAddress
)
{
// we are filling in an IP address
TransportAddress.choice = ipAddress_chosen;
// fill in the port
TransportAddress.u.ipAddress.port = Port;
// value is a ptr to a struct, so it can't be null
_ASSERTE(NULL != TransportAddress.u.ipAddress.ip.value);
// 4 bytes in the IP address
// copy the bytes into the transport address array
TransportAddress.u.ipAddress.ip.length = 4;
*((DWORD *)TransportAddress.u.ipAddress.ip.value) =
htonl(IPv4Address);
}
static __inline void FillTransportAddress (
IN const SOCKADDR_IN & SocketAddress,
OUT TransportAddress & ReturnTransportAddress)
{
FillTransportAddress (
ntohl (SocketAddress.sin_addr.s_addr),
ntohs (SocketAddress.sin_port),
ReturnTransportAddress);
}
// returns E_INVALIDARG for PDUs which can not be handled.
__inline HRESULT
GetTransportInfo(
IN const TransportAddress &TransportAddress,
OUT DWORD &IPv4Address, // host order
OUT WORD &Port // host order
)
{
// we proceed only if the transport address has the
// IP address (v4) field filled
if (!(ipAddress_chosen & TransportAddress.choice))
{
DebugF( _T("GetTransportInfo(&H245Address, &0x%x, &%u), ")
_T("non unicast address type = %d, returning E_INVALIDARG\n"),
IPv4Address, Port, TransportAddress.choice);
return E_INVALIDARG;
}
// fill in the port
Port = TransportAddress.u.ipAddress.port;
// 4 bytes in the IP address
// copy the bytes into the transport address array
if (4 != TransportAddress.u.ipAddress.ip.length)
{
DebugF( _T("GetTransportInfo: bogus address length (%d) in TransportAddress\n"),
TransportAddress.u.ipAddress.ip.length);
return E_INVALIDARG;
}
IPv4Address = ntohl(*((DWORD *)TransportAddress.u.ipAddress.ip.value));
return S_OK;
}
static __inline HRESULT GetTransportInfo (
IN const TransportAddress & TransportAddress,
OUT SOCKADDR_IN & ReturnSocketAddress)
{
HRESULT Result;
ReturnSocketAddress.sin_family = AF_INET;
Result = GetTransportInfo (TransportAddress,
ReturnSocketAddress.sin_addr.s_addr,
ReturnSocketAddress.sin_port);
ReturnSocketAddress.sin_addr.s_addr = htonl (ReturnSocketAddress.sin_addr.s_addr);
ReturnSocketAddress.sin_port = htons (ReturnSocketAddress.sin_port);
return Result;
}
// fills the H245TransportAddress port and address bytes with
// those specified. assumes that the passed in values are
// in host order
inline void
FillH245TransportAddress(
IN DWORD IPv4Address,
IN WORD Port,
OUT H245TransportAddress &H245Address
)
{
// we are filling in an unicast IP address
H245Address.choice = unicastAddress_chosen;
// alias for the unicast address
UnicastAddress &UnicastIPAddress = H245Address.u.unicastAddress;
// its an IP address
UnicastIPAddress.choice = UnicastAddress_iPAddress_chosen;
// fill in the port
UnicastIPAddress.u.iPAddress.tsapIdentifier = Port;
// value is a ptr to a struct, so it can't be null
_ASSERTE(NULL != UnicastIPAddress.u.iPAddress.network.value);
// 4 bytes in the IP address
// copy the bytes into the transport address array
UnicastIPAddress.u.iPAddress.network.length = 4;
*((DWORD *)UnicastIPAddress.u.iPAddress.network.value) =
htonl(IPv4Address);
}
// Returned IPaddress and port are in host order
inline HRESULT
GetH245TransportInfo(
IN const H245TransportAddress &H245Address,
OUT DWORD &IPv4Address,
OUT WORD &Port
)
{
// we proceed only if the transport address has a unicast address
if (!(unicastAddress_chosen & H245Address.choice))
{
DebugF( _T("GetH245TransportInfo(&H245Address, &0x%x, &%u), ")
_T("non unicast address type = %d, returning E_INVALIDARG\n"),
IPv4Address, Port, H245Address.choice);
return E_INVALIDARG;
}
// we proceed only if the transport address has the
// IP address (v4) field filled
if (!(UnicastAddress_iPAddress_chosen &
H245Address.u.unicastAddress.choice))
{
DebugF( _T("GetH245TransportInfo(&TransportAddress, &0x%x, &%u), ")
_T("non ip address type = %d, returning E_INVALIDARG\n"),
IPv4Address, Port, H245Address.u.unicastAddress.choice);
return E_INVALIDARG;
}
const UnicastAddress & UnicastIPAddress = H245Address.u.unicastAddress;
// fill in the port
Port = UnicastIPAddress.u.iPAddress.tsapIdentifier;
// 4 bytes in the IP address
// copy the bytes into the transport address array
if (4 != UnicastIPAddress.u.iPAddress.network.length)
{
DebugF( _T("GetH245TransportInfo: bogus ip address length (%d), failing\n"),
UnicastIPAddress.u.iPAddress.network.length);
return E_INVALIDARG;
}
// value is a ptr to a struct, so it can't be null
_ASSERTE(NULL != UnicastIPAddress.u.iPAddress.network.value);
IPv4Address = ntohl(*((DWORD *)UnicastIPAddress.u.iPAddress.network.value));
return S_OK;
}
static __inline HRESULT GetH245TransportInfo (
IN const H245TransportAddress & H245Address,
OUT SOCKADDR_IN * ReturnSocketAddress)
{
DWORD IPAddress;
WORD Port;
HRESULT Result;
Result = GetH245TransportInfo (H245Address, IPAddress, Port);
if (Result == S_OK) {
ReturnSocketAddress -> sin_family = AF_INET;
ReturnSocketAddress -> sin_addr.s_addr = htonl (IPAddress);
ReturnSocketAddress -> sin_port = htons (Port);
}
return Result;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Routines dealing with the T.120 Parameters in H.245 PDUs //
// //
///////////////////////////////////////////////////////////////////////////////
// In case of failure the routine returns
// INADDR_NONE for the T120ConnectToIPAddr
inline HRESULT
GetT120ConnectToAddress(
IN NetworkAccessParameters separateStack,
OUT DWORD &T120ConnectToIPAddr,
OUT WORD &T120ConnectToPort
)
{
// These are the return values in case of a failure.
T120ConnectToIPAddr = INADDR_NONE;
T120ConnectToPort = 0;
// CODEWORK: should we require the distribution member
// to be present always ?
if ((separateStack.bit_mask & distribution_present) &&
(separateStack.distribution.choice != unicast_chosen))
{
// We support Unicast only
return E_INVALIDARG;
}
// Deal with t120SetupProcedure
if (separateStack.networkAddress.choice != localAreaAddress_chosen)
{
// Support only local area addresses
return E_INVALIDARG;
}
GetH245TransportInfo(
separateStack.networkAddress.u.localAreaAddress,
T120ConnectToIPAddr,
T120ConnectToPort
);
DebugF (_T ("T120: Endpoint is listening on: %08X:%04X.\n"),
T120ConnectToIPAddr,
T120ConnectToPort
);
return S_OK;
}
#define TPKT_HEADER_SIZE 4
#define TPKT_VERSION 3
inline DWORD GetPktLenFromTPKTHdr(BYTE *pbTpktHdr)
/*++
Routine Description:
Compute the length of the packet from the TPKT header.
The TPKT header is four bytes long. Byte 0 gives
the TPKT version (defined by TPKT_VERSION). Byte 1
is reserved and should not be interpreted. Bytes 2 and 3
together give the size of the packet (Byte 2 is the MSB and
Byte 3 is the LSB i.e. in network byte order). (This assumes
that the size of the packet will always fit in 2 bytes).
Arguments:
Return Values:
Returns the length of the PDU which follows the TPKT header.
--*/
{
_ASSERTE(pbTpktHdr[0] == TPKT_VERSION);
return ((pbTpktHdr[2] << 8) + pbTpktHdr[3] - TPKT_HEADER_SIZE);
}
inline void SetupTPKTHeader(
OUT BYTE * pbTpktHdr,
IN DWORD dwLength
)
/*++
Routine Description:
Setup the TPKT header based on the length.
The TPKT header is four bytes long. Byte 0 gives
the TPKT version (defined by TPKT_VERSION). Byte 1
is reserved and should not be interpreted. Bytes 2 and 3
together give the size of the packet (Byte 2 is the MSB and
Byte 3 is the LSB i.e. in network byte order). (This assumes
that the size of the packet will always fit in 2 bytes).
Arguments:
Return Values:
Returns S_OK if the version is right and E_FAIL otherwise.
--*/
{
_ASSERTE(pbTpktHdr);
dwLength += TPKT_HEADER_SIZE;
// TPKT requires that the packet size fit in two bytes.
_ASSERTE(dwLength < (1L << 16));
pbTpktHdr[0] = TPKT_VERSION;
pbTpktHdr[1] = 0;
pbTpktHdr[2] = HIBYTE(dwLength); //(BYTE)(dwLength >> 8);
pbTpktHdr[3] = LOBYTE(dwLength); //(BYTE)dwLength;
}
static __inline BOOLEAN RtlEqualStringConst (
IN const STRING * StringA,
IN const STRING * StringB,
IN BOOLEAN CaseInSensitive)
{
return RtlEqualString (
const_cast<STRING *> (StringA),
const_cast<STRING *> (StringB),
CaseInSensitive);
}
static __inline INT RtlCompareStringConst (
IN const STRING * StringA,
IN const STRING * StringB,
IN BOOLEAN CaseInSensitive)
{
return RtlCompareString (
const_cast<STRING *> (StringA),
const_cast<STRING *> (StringB),
CaseInSensitive);
}
static __inline void InitializeAnsiString (
OUT ANSI_STRING * AnsiString,
IN ASN1octetstring_t * AsnString)
{
assert (AnsiString);
assert (AsnString);
AnsiString -> Buffer = (PSTR) AsnString -> value;
AnsiString -> Length = (USHORT) AsnString -> length / sizeof (CHAR);
}
static __inline void InitializeUnicodeString (
OUT UNICODE_STRING * UnicodeString,
IN ASN1char16string_t * AsnString)
{
assert (UnicodeString);
assert (AsnString);
UnicodeString -> Buffer = (PWSTR)AsnString -> value;
UnicodeString -> Length = (USHORT) AsnString -> length / sizeof (WCHAR);
}
// use with "%.*s" or "%.*S"
#define ANSI_STRING_PRINTF(AnsiString) (AnsiString) -> Length, (AnsiString) -> Buffer
// { Length, MaximumLength, Buffer }
#define ANSI_STRING_INIT(Text) { sizeof (Text) - sizeof (CHAR), 0, (Text) } // account for NUL
void FreeAnsiString (
IN ANSI_STRING * String);
NTSTATUS CopyAnsiString (
IN ANSI_STRING * SourceString,
OUT ANSI_STRING * DestString);
static __inline ULONG ByteSwap (
IN ULONG Value)
{
union ULONG_SWAP {
BYTE Bytes [sizeof (ULONG)];
ULONG Integer;
};
ULONG_SWAP * SwapValue;
ULONG_SWAP SwapResult;
SwapValue = (ULONG_SWAP *) &Value;
SwapResult.Bytes [0] = SwapValue -> Bytes [3];
SwapResult.Bytes [1] = SwapValue -> Bytes [2];
SwapResult.Bytes [2] = SwapValue -> Bytes [1];
SwapResult.Bytes [3] = SwapValue -> Bytes [0];
return SwapResult.Integer;
}
// does NOT convert to host order first
static __inline INT Compare_SOCKADDR_IN (
IN const SOCKADDR_IN * AddressA,
IN const SOCKADDR_IN * AddressB)
{
assert (AddressA);
assert (AddressB);
if (AddressA -> sin_addr.s_addr < AddressB -> sin_addr.s_addr) return -1;
if (AddressA -> sin_addr.s_addr > AddressB -> sin_addr.s_addr) return 1;
return 0;
}
static __inline BOOL IsEqualSocketAddress (
IN const SOCKADDR_IN * AddressA,
IN const SOCKADDR_IN * AddressB)
{
assert (AddressA);
assert (AddressB);
assert (AddressA -> sin_family == AF_INET);
assert (AddressB -> sin_family == AF_INET);
return AddressA -> sin_addr.s_addr == AddressB -> sin_addr.s_addr
&& AddressA -> sin_port == AddressB -> sin_port;
}
#if DBG
void ExposeTimingWindow (void);
#endif
// Get the address of the best interface that will
// be used to connect to the DestinationAddress
ULONG GetBestInterfaceAddress (
IN DWORD DestinationAddress, // host order
OUT DWORD * InterfaceAddress); // host order
DWORD
H323MapAdapterToAddress (
IN DWORD AdapterIndex
);
#endif // __h323ics_util_h