michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set sw=2 ts=8 et tw=80 : */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__ michael@0: #define __IPC_GLUE_IPCMESSAGEUTILS_H__ michael@0: michael@0: #include "base/process_util.h" michael@0: #include "chrome/common/ipc_message_utils.h" michael@0: michael@0: #include "mozilla/ArrayUtils.h" michael@0: #include "mozilla/TimeStamp.h" michael@0: #ifdef XP_WIN michael@0: #include "mozilla/TimeStamp_windows.h" michael@0: #endif michael@0: #include "mozilla/TypedEnum.h" michael@0: #include "mozilla/IntegerTypeTraits.h" michael@0: michael@0: #include michael@0: michael@0: #include "nsID.h" michael@0: #include "nsMemory.h" michael@0: #include "nsString.h" michael@0: #include "nsTArray.h" michael@0: #include "js/StructuredClone.h" michael@0: #include "nsCSSProperty.h" michael@0: michael@0: #ifdef _MSC_VER michael@0: #pragma warning( disable : 4800 ) michael@0: #endif michael@0: michael@0: #if !defined(OS_POSIX) michael@0: // This condition must be kept in sync with the one in michael@0: // ipc_message_utils.h, but this dummy definition of michael@0: // base::FileDescriptor acts as a static assert that we only get one michael@0: // def or the other (or neither, in which case code using michael@0: // FileDescriptor fails to build) michael@0: namespace base { struct FileDescriptor { }; } michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: michael@0: // This is a cross-platform approximation to HANDLE, which we expect michael@0: // to be typedef'd to void* or thereabouts. michael@0: typedef uintptr_t WindowsHandle; michael@0: michael@0: // XXX there are out of place and might be generally useful. Could michael@0: // move to nscore.h or something. michael@0: struct void_t { michael@0: bool operator==(const void_t&) const { return true; } michael@0: }; michael@0: struct null_t { michael@0: bool operator==(const null_t&) const { return true; } michael@0: }; michael@0: michael@0: struct SerializedStructuredCloneBuffer michael@0: { michael@0: SerializedStructuredCloneBuffer() michael@0: : data(nullptr), dataLength(0) michael@0: { } michael@0: michael@0: SerializedStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& aOther) michael@0: { michael@0: *this = aOther; michael@0: } michael@0: michael@0: bool michael@0: operator==(const SerializedStructuredCloneBuffer& aOther) const michael@0: { michael@0: return this->data == aOther.data && michael@0: this->dataLength == aOther.dataLength; michael@0: } michael@0: michael@0: SerializedStructuredCloneBuffer& michael@0: operator=(const JSAutoStructuredCloneBuffer& aOther) michael@0: { michael@0: data = aOther.data(); michael@0: dataLength = aOther.nbytes(); michael@0: return *this; michael@0: } michael@0: michael@0: uint64_t* data; michael@0: size_t dataLength; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: namespace IPC { michael@0: michael@0: /** michael@0: * Generic enum serializer. michael@0: * michael@0: * Consider using the specializations below, such as ContiguousEnumSerializer. michael@0: * michael@0: * This is a generic serializer for any enum type used in IPDL. michael@0: * Programmers can define ParamTraits for enum type E by deriving michael@0: * EnumSerializer where MyEnumValidator is a struct michael@0: * that has to define a static IsLegalValue function returning whether michael@0: * a given value is a legal value of the enum type at hand. michael@0: * michael@0: * \sa https://developer.mozilla.org/en/IPDL/Type_Serialization michael@0: */ michael@0: template michael@0: struct EnumSerializer { michael@0: typedef E paramType; michael@0: typedef typename mozilla::UnsignedStdintTypeForSize::Type michael@0: uintParamType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aValue) { michael@0: MOZ_ASSERT(EnumValidator::IsLegalValue(aValue)); michael@0: WriteParam(aMsg, uintParamType(aValue)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { michael@0: uintParamType value; michael@0: if(!ReadParam(aMsg, aIter, &value) || michael@0: !EnumValidator::IsLegalValue(paramType(value))) { michael@0: return false; michael@0: } michael@0: *aResult = paramType(value); michael@0: return true; michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct ContiguousEnumValidator michael@0: { michael@0: static bool IsLegalValue(E e) michael@0: { michael@0: return MinLegal <= e && e < HighBound; michael@0: } michael@0: }; michael@0: michael@0: template michael@0: class ContiguousTypedEnumValidator michael@0: { michael@0: // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8: michael@0: // "comparison of unsigned expression >= 0 is always true" michael@0: // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856 michael@0: template michael@0: static bool IsLessThanOrEqual(T a, T b) { return a <= b; } michael@0: michael@0: public: michael@0: static bool IsLegalValue(E e) michael@0: { michael@0: typedef MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) ActualEnumType; michael@0: return IsLessThanOrEqual(MinLegal, ActualEnumType(e)) && michael@0: ActualEnumType(e) < HighBound; michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct BitFlagsEnumValidator michael@0: { michael@0: static bool IsLegalValue(E e) michael@0: { michael@0: return (e & AllBits) == e; michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct BitFlagsTypedEnumValidator michael@0: { michael@0: static bool IsLegalValue(E e) michael@0: { michael@0: return (e & AllBits) == e; michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * Specialization of EnumSerializer for enums with contiguous enum values. michael@0: * michael@0: * Provide two values: MinLegal, HighBound. An enum value x will be michael@0: * considered legal if MinLegal <= x < HighBound. michael@0: * michael@0: * For example, following is definition of serializer for enum type FOO. michael@0: * \code michael@0: * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO }; michael@0: * michael@0: * template <> michael@0: * struct ParamTraits: michael@0: * public ContiguousEnumSerializer {}; michael@0: * \endcode michael@0: * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value. michael@0: */ michael@0: template michael@0: struct ContiguousEnumSerializer michael@0: : EnumSerializer> michael@0: {}; michael@0: michael@0: /** michael@0: * Similar to ContiguousEnumSerializer, but for MFBT typed enums michael@0: * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when michael@0: * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly. michael@0: */ michael@0: template michael@0: struct ContiguousTypedEnumSerializer michael@0: : EnumSerializer> michael@0: {}; michael@0: michael@0: /** michael@0: * Specialization of EnumSerializer for enums representing bit flags. michael@0: * michael@0: * Provide one value: AllBits. An enum value x will be michael@0: * considered legal if (x & AllBits) == x; michael@0: * michael@0: * Example: michael@0: * \code michael@0: * enum FOO { michael@0: * FOO_FIRST = 1 << 0, michael@0: * FOO_SECOND = 1 << 1, michael@0: * FOO_LAST = 1 << 2, michael@0: * ALL_BITS = (1 << 3) - 1 michael@0: * }; michael@0: * michael@0: * template <> michael@0: * struct ParamTraits: michael@0: * public BitFlagsEnumSerializer {}; michael@0: * \endcode michael@0: */ michael@0: template michael@0: struct BitFlagsEnumSerializer michael@0: : EnumSerializer> michael@0: {}; michael@0: michael@0: /** michael@0: * Similar to BitFlagsEnumSerializer, but for MFBT typed enums michael@0: * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when michael@0: * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly. michael@0: */ michael@0: template michael@0: struct BitFlagsTypedEnumSerializer michael@0: : EnumSerializer> michael@0: {}; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: : public ContiguousEnumSerializer michael@0: { }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef int8_t paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: aMsg->WriteBytes(&aParam, sizeof(aParam)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: const char* outp; michael@0: if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult))) michael@0: return false; michael@0: michael@0: *aResult = *reinterpret_cast(outp); michael@0: return true; michael@0: } michael@0: }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef uint8_t paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: aMsg->WriteBytes(&aParam, sizeof(aParam)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: const char* outp; michael@0: if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult))) michael@0: return false; michael@0: michael@0: *aResult = *reinterpret_cast(outp); michael@0: return true; michael@0: } michael@0: }; michael@0: michael@0: #if !defined(OS_POSIX) michael@0: // See above re: keeping definitions in sync michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef base::FileDescriptor paramType; michael@0: static void Write(Message* aMsg, const paramType& aParam) { michael@0: NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform"); michael@0: } michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { michael@0: NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform"); michael@0: return false; michael@0: } michael@0: }; michael@0: #endif // !defined(OS_POSIX) michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef nsACString paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: bool isVoid = aParam.IsVoid(); michael@0: aMsg->WriteBool(isVoid); michael@0: michael@0: if (isVoid) michael@0: // represents a nullptr pointer michael@0: return; michael@0: michael@0: uint32_t length = aParam.Length(); michael@0: WriteParam(aMsg, length); michael@0: aMsg->WriteBytes(aParam.BeginReading(), length); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: bool isVoid; michael@0: if (!aMsg->ReadBool(aIter, &isVoid)) michael@0: return false; michael@0: michael@0: if (isVoid) { michael@0: aResult->SetIsVoid(true); michael@0: return true; michael@0: } michael@0: michael@0: uint32_t length; michael@0: if (ReadParam(aMsg, aIter, &length)) { michael@0: const char* buf; michael@0: if (aMsg->ReadBytes(aIter, &buf, length)) { michael@0: aResult->Assign(buf, length); michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: if (aParam.IsVoid()) michael@0: aLog->append(L"(NULL)"); michael@0: else michael@0: aLog->append(UTF8ToWide(aParam.BeginReading())); michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef nsAString paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: bool isVoid = aParam.IsVoid(); michael@0: aMsg->WriteBool(isVoid); michael@0: michael@0: if (isVoid) michael@0: // represents a nullptr pointer michael@0: return; michael@0: michael@0: uint32_t length = aParam.Length(); michael@0: WriteParam(aMsg, length); michael@0: aMsg->WriteBytes(aParam.BeginReading(), length * sizeof(char16_t)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: bool isVoid; michael@0: if (!aMsg->ReadBool(aIter, &isVoid)) michael@0: return false; michael@0: michael@0: if (isVoid) { michael@0: aResult->SetIsVoid(true); michael@0: return true; michael@0: } michael@0: michael@0: uint32_t length; michael@0: if (ReadParam(aMsg, aIter, &length)) { michael@0: const char16_t* buf; michael@0: if (aMsg->ReadBytes(aIter, reinterpret_cast(&buf), michael@0: length * sizeof(char16_t))) { michael@0: aResult->Assign(buf, length); michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: if (aParam.IsVoid()) michael@0: aLog->append(L"(NULL)"); michael@0: else { michael@0: #ifdef WCHAR_T_IS_UTF16 michael@0: aLog->append(reinterpret_cast(aParam.BeginReading())); michael@0: #else michael@0: uint32_t length = aParam.Length(); michael@0: for (uint32_t index = 0; index < length; index++) { michael@0: aLog->push_back(std::wstring::value_type(aParam[index])); michael@0: } michael@0: #endif michael@0: } michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits : ParamTraits michael@0: { michael@0: typedef nsCString paramType; michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits : ParamTraits michael@0: { michael@0: typedef nsLiteralCString paramType; michael@0: }; michael@0: michael@0: #ifdef MOZILLA_INTERNAL_API michael@0: michael@0: template<> michael@0: struct ParamTraits : ParamTraits michael@0: { michael@0: typedef nsAutoCString paramType; michael@0: }; michael@0: michael@0: #endif // MOZILLA_INTERNAL_API michael@0: michael@0: template <> michael@0: struct ParamTraits : ParamTraits michael@0: { michael@0: typedef nsString paramType; michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits : ParamTraits michael@0: { michael@0: typedef nsLiteralString paramType; michael@0: }; michael@0: michael@0: template michael@0: struct ParamTraits > michael@0: { michael@0: typedef FallibleTArray paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: uint32_t length = aParam.Length(); michael@0: WriteParam(aMsg, length); michael@0: for (uint32_t index = 0; index < length; index++) { michael@0: WriteParam(aMsg, aParam[index]); michael@0: } michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: uint32_t length; michael@0: if (!ReadParam(aMsg, aIter, &length)) { michael@0: return false; michael@0: } michael@0: michael@0: aResult->SetCapacity(length); michael@0: for (uint32_t index = 0; index < length; index++) { michael@0: E* element = aResult->AppendElement(); michael@0: if (!(element && ReadParam(aMsg, aIter, element))) { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: for (uint32_t index = 0; index < aParam.Length(); index++) { michael@0: if (index) { michael@0: aLog->append(L" "); michael@0: } michael@0: LogParam(aParam[index], aLog); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct ParamTraits > michael@0: { michael@0: typedef InfallibleTArray paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, static_cast&>(aParam)); michael@0: } michael@0: michael@0: // deserialize the array fallibly, but return an InfallibleTArray michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: FallibleTArray temp; michael@0: if (!ReadParam(aMsg, aIter, &temp)) michael@0: return false; michael@0: michael@0: aResult->SwapElements(temp); michael@0: return true; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: LogParam(static_cast&>(aParam), aLog); michael@0: } michael@0: }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef float paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: aMsg->WriteBytes(&aParam, sizeof(paramType)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: const char* outFloat; michael@0: if (!aMsg->ReadBytes(aIter, &outFloat, sizeof(float))) michael@0: return false; michael@0: *aResult = *reinterpret_cast(outFloat); michael@0: return true; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: aLog->append(StringPrintf(L"%g", aParam)); michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: : public ContiguousEnumSerializer michael@0: {}; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::void_t paramType; michael@0: static void Write(Message* aMsg, const paramType& aParam) { } michael@0: static bool michael@0: Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: *aResult = paramType(); michael@0: return true; michael@0: } michael@0: }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::null_t paramType; michael@0: static void Write(Message* aMsg, const paramType& aParam) { } michael@0: static bool michael@0: Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: *aResult = paramType(); michael@0: return true; michael@0: } michael@0: }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef nsID paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.m0); michael@0: WriteParam(aMsg, aParam.m1); michael@0: WriteParam(aMsg, aParam.m2); michael@0: for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) { michael@0: WriteParam(aMsg, aParam.m3[i]); michael@0: } michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: if(!ReadParam(aMsg, aIter, &(aResult->m0)) || michael@0: !ReadParam(aMsg, aIter, &(aResult->m1)) || michael@0: !ReadParam(aMsg, aIter, &(aResult->m2))) michael@0: return false; michael@0: michael@0: for (unsigned int i = 0; i < mozilla::ArrayLength(aResult->m3); i++) michael@0: if (!ReadParam(aMsg, aIter, &(aResult->m3[i]))) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: aLog->append(L"{"); michael@0: aLog->append(StringPrintf(L"%8.8X-%4.4X-%4.4X-", michael@0: aParam.m0, michael@0: aParam.m1, michael@0: aParam.m2)); michael@0: for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) michael@0: aLog->append(StringPrintf(L"%2.2X", aParam.m3[i])); michael@0: aLog->append(L"}"); michael@0: } michael@0: }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::TimeDuration paramType; michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.mValue); michael@0: } michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: return ReadParam(aMsg, aIter, &aResult->mValue); michael@0: }; michael@0: }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::TimeStamp paramType; michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.mValue); michael@0: } michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: return ReadParam(aMsg, aIter, &aResult->mValue); michael@0: }; michael@0: }; michael@0: michael@0: #ifdef XP_WIN michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::TimeStampValue paramType; michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.mGTC); michael@0: WriteParam(aMsg, aParam.mQPC); michael@0: WriteParam(aMsg, aParam.mHasQPC); michael@0: WriteParam(aMsg, aParam.mIsNull); michael@0: } michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: return (ReadParam(aMsg, aIter, &aResult->mGTC) && michael@0: ReadParam(aMsg, aIter, &aResult->mQPC) && michael@0: ReadParam(aMsg, aIter, &aResult->mHasQPC) && michael@0: ReadParam(aMsg, aIter, &aResult->mIsNull)); michael@0: } michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::SerializedStructuredCloneBuffer paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.dataLength); michael@0: if (aParam.dataLength) { michael@0: // Structured clone data must be 64-bit aligned. michael@0: aMsg->WriteBytes(aParam.data, aParam.dataLength, sizeof(uint64_t)); michael@0: } michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: if (!ReadParam(aMsg, aIter, &aResult->dataLength)) { michael@0: return false; michael@0: } michael@0: michael@0: if (aResult->dataLength) { michael@0: const char** buffer = michael@0: const_cast(reinterpret_cast(&aResult->data)); michael@0: // Structured clone data must be 64-bit aligned. michael@0: if (!aMsg->ReadBytes(aIter, buffer, aResult->dataLength, michael@0: sizeof(uint64_t))) { michael@0: return false; michael@0: } michael@0: } else { michael@0: aResult->data = nullptr; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: LogParam(aParam.dataLength, aLog); michael@0: } michael@0: }; michael@0: michael@0: } /* namespace IPC */ michael@0: michael@0: #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */