(file) Return to messages.c CVS log (file) (dir) Up to [OMI] / omi / base

File: [OMI] / omi / base / messages.c (download)
Revision: 1.1.1.1 (vendor branch), Wed May 30 21:47:49 2012 UTC (12 years ago) by mike
Branch: TOG
CVS Tags: OMI_1_0_2_Branch, OMI_1_0_2, OMI_1_0_1_PRE, OMI_1_0_1, OMI_1_0_0
Changes since 1.1: +0 -0 lines
Initial Import

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
** use this file except in compliance with the License. You may obtain a copy 
** of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

#include "messages.h"
#include "packing.h"
#include <assert.h>
#include "result.h"
#include "io.h"

/*
**==============================================================================
**
** Local definitions
**
**==============================================================================
*/

typedef enum _FieldType
{
    FT_BOOLEAN = MI_BOOLEAN,
    FT_UINT8 = MI_UINT8,
    FT_SINT8 = MI_SINT8,
    FT_UINT16 = MI_UINT16,
    FT_SINT16 = MI_SINT16,
    FT_UINT32 = MI_UINT32,
    FT_SINT32 = MI_SINT32,
    FT_UINT64 = MI_UINT64,
    FT_SINT64 = MI_SINT64,
    FT_REAL32 = MI_REAL32,
    FT_REAL64 = MI_REAL64,
    FT_CHAR16 = MI_CHAR16,
    FT_DATETIME = MI_DATETIME,
    FT_STRING = MI_STRING,
    FT_REFERENCE = MI_REFERENCE,
    FT_INSTANCE = MI_INSTANCE,
    FT_BOOLEANA = MI_BOOLEANA,
    FT_UINT8A = MI_UINT8A,
    FT_SINT8A = MI_SINT8A,
    FT_UINT16A = MI_UINT16A,
    FT_SINT16A = MI_SINT16A,
    FT_UINT32A = MI_UINT32A,
    FT_SINT32A = MI_SINT32A,
    FT_UINT64A = MI_UINT64A,
    FT_SINT64A = MI_SINT64A,
    FT_REAL32A = MI_REAL32A,
    FT_REAL64A = MI_REAL64A,
    FT_CHAR16A = MI_CHAR16A,
    FT_DATETIMEA = MI_DATETIMEA,
    FT_STRINGA = MI_STRINGA,
    FT_REFERENCEA = MI_REFERENCEA,
    FT_INSTANCEA = MI_INSTANCEA,
    FT_RESULT,
    FT_ATOMIC
}
FieldType;

/* Defines meta data for message field (to support printing) */
typedef struct Field
{
    /* Name of field */
    const char* name;

    /* (T=Tag, S=String, B=Boolean, A=StringArray, O=Object) */
    FieldType type;

    /* Byte off within structure to this field */
    size_t off;
}
Field;

typedef enum _MessageFieldType
{
    MFT_END_OF_LIST,    /* special type to terminate list of fields */
    MFT_POINTER,        /* Pointer that has to be converted */
    MFT_POINTER_OPT,    /* Pointer that has to be converted (may be null) */
    MFT_POINTER_SET_NULL,   /* Pointer that has to be nullified instead of converting */
    MFT_INSTANCE,       /* instance */
    MFT_INSTANCE_OPT    /* instance  (maybe NULL) */
}
MessageFieldType;

/* Defines meta data for message field (to support packing/unpacking) */
typedef struct _MessageField
{
    /* (T=Tag, S=String, B=Boolean, A=StringArray, O=Object) */
    MessageFieldType type;

    /* Byte off within structure to this field and (for instance) to packed pointer/size */
    size_t off;
    size_t offPackedPtr;
    size_t offPackedSize;
}
MessageField;

static const MessageField baseMessageFields[] = 
{
    {MFT_POINTER_SET_NULL,offsetof(Message, next),0,0},
    {MFT_POINTER_SET_NULL,offsetof(Message, prev),0,0},
    {MFT_POINTER_SET_NULL,offsetof(Message, request),0,0},
    {MFT_POINTER_SET_NULL,offsetof(Message, callback),0,0},
    {MFT_POINTER_SET_NULL,offsetof(Message, callbackData),0,0},
    {MFT_POINTER_SET_NULL,offsetof(Message, dtor),0,0},
    {MFT_POINTER_SET_NULL,offsetof(Message, dtorData),0,0},
    {MFT_POINTER_OPT,offsetof(Message, libraryName),0,0},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField emptyMessageFields[] = 
{
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField getInstanceMessageFields[] = 
{
    {MFT_POINTER,offsetof(GetInstanceReq, nameSpace),0,0},
    {MFT_INSTANCE,offsetof(GetInstanceReq, instanceName),offsetof(GetInstanceReq, packedInstanceNamePtr),offsetof(GetInstanceReq, packedInstanceNameSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField postInstanceMessageFields[] = 
{
    {MFT_INSTANCE,offsetof(PostInstanceMsg, instance),offsetof(PostInstanceMsg, packedInstancePtr),offsetof(PostInstanceMsg, packedInstanceSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField enumerateInstancesMessageFields[] = 
{
    {MFT_POINTER,offsetof(EnumerateInstancesReq, nameSpace),0,0},
    {MFT_POINTER,offsetof(EnumerateInstancesReq, className),0,0},
    {MFT_POINTER_OPT,offsetof(EnumerateInstancesReq, requestClassName),0,0},
    {MFT_POINTER_OPT,offsetof(EnumerateInstancesReq, queryLanguage),0,0},
    {MFT_POINTER_OPT,offsetof(EnumerateInstancesReq, queryExpression),0,0},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField invokeMessageFields[] = 
{
    {MFT_POINTER,offsetof(InvokeReq, nameSpace),0,0},
    {MFT_POINTER,offsetof(InvokeReq, function),0,0},
    {MFT_POINTER_OPT,offsetof(InvokeReq, className),0,0},
    {MFT_INSTANCE_OPT,offsetof(InvokeReq, instance),offsetof(InvokeReq, packedInstancePtr),offsetof(InvokeReq, packedInstanceSize)},
    {MFT_INSTANCE_OPT,offsetof(InvokeReq, instanceParams),offsetof(InvokeReq, packedInstanceParamsPtr),offsetof(InvokeReq, packedInstanceParamsSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField associatorsOfMessageFields[] = 
{
    {MFT_POINTER,offsetof(AssociatorsOfReq, nameSpace),0,0},
    {MFT_POINTER_OPT,offsetof(AssociatorsOfReq, className),0,0},
    {MFT_POINTER_OPT,offsetof(AssociatorsOfReq, assocClass),0,0},
    {MFT_POINTER_OPT,offsetof(AssociatorsOfReq, resultClass),0,0},
    {MFT_POINTER_OPT,offsetof(AssociatorsOfReq, role),0,0},
    {MFT_POINTER_OPT,offsetof(AssociatorsOfReq, resultRole),0,0},
    {MFT_INSTANCE,offsetof(AssociatorsOfReq, instance),offsetof(AssociatorsOfReq, packedInstancePtr),offsetof(AssociatorsOfReq, packedInstanceSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField referencesOfMessageFields[] = 
{
    {MFT_POINTER,offsetof(ReferencesOfReq, nameSpace),0,0},
    {MFT_POINTER_OPT,offsetof(ReferencesOfReq, className),0,0},
    {MFT_POINTER_OPT,offsetof(ReferencesOfReq, assocClass),0,0},
    {MFT_POINTER_OPT,offsetof(ReferencesOfReq, role),0,0},
    {MFT_INSTANCE,offsetof(ReferencesOfReq, instance),offsetof(ReferencesOfReq, packedInstancePtr),offsetof(ReferencesOfReq, packedInstanceSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField subscribeRequestMessageFields[] = 
{
    {MFT_POINTER,offsetof(SubscribeReq, nameSpace),0,0},
    {MFT_POINTER,offsetof(SubscribeReq, className),0,0},
    {MFT_POINTER,offsetof(SubscribeReq, filter),0,0},
    {MFT_POINTER,offsetof(SubscribeReq, language),0,0},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField subscribeResponseMessageFields[] = 
{
    {MFT_POINTER,offsetof(SubscribeRes, subscriptionID),0,0},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField deleteInstanceMessageFields[] = 
{
    {MFT_POINTER,offsetof(DeleteInstanceReq, nameSpace),0,0},
    {MFT_INSTANCE,offsetof(DeleteInstanceReq, instanceName),offsetof(DeleteInstanceReq, packedInstanceNamePtr),offsetof(DeleteInstanceReq, packedInstanceNameSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField createInstanceMessageFields[] = 
{
    {MFT_POINTER,offsetof(CreateInstanceReq, nameSpace),0,0},
    {MFT_INSTANCE,offsetof(CreateInstanceReq, instance),offsetof(CreateInstanceReq, packedInstancePtr),offsetof(CreateInstanceReq, packedInstanceSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField modifyInstanceMessageFields[] = 
{
    {MFT_POINTER,offsetof(ModifyInstanceReq, nameSpace),0,0},
    {MFT_INSTANCE,offsetof(ModifyInstanceReq, instance),offsetof(ModifyInstanceReq, packedInstancePtr),offsetof(ModifyInstanceReq, packedInstanceSize)},
    {MFT_END_OF_LIST, 0, 0, 0}
};

static const MessageField binProtocolNotificationFields[] = 
{
    {MFT_POINTER_OPT,offsetof(BinProtocolNotification, user),0,0},
    {MFT_POINTER_OPT,offsetof(BinProtocolNotification, password),0,0},
    {MFT_POINTER_OPT,offsetof(BinProtocolNotification, authFile),0,0},
    {MFT_END_OF_LIST, 0, 0, 0}
};

/* Entries in this array corresponds to MessageTag values:
    GetInstanceReqTag = 1,
    PostInstanceMsgTag = 2,
    EnumerateInstancesReqTag = 3,
    PostResultMsgTag = 4,
    NoOpReqTag = 5,
    NoOpRspTag = 6,
    DispResultMsgTag = 7,
    InvokeReqTag = 8,
    AssociatorsOfReqTag = 9,
    ReferencesOfReqTag = 10,
    SubscribeReqTag = 11,
    SubscribeResTag = 12,
    DeleteInstanceReqTag = 13,
    CreateInstanceReqTag = 14,
    ModifyInstanceReqTag = 15,
    BinProtocolNotificationTag = 16
*/
typedef struct _MessageDeclaration
{
    const MessageField* fields;
    size_t              size;
    MI_Boolean          cloneRequired;
}
MessageDeclaration;

static const MessageDeclaration allMessages[] = {
    {baseMessageFields,                 0,                       MI_FALSE},
    {getInstanceMessageFields,          sizeof(GetInstanceReq),   MI_TRUE},
    {postInstanceMessageFields,         sizeof(PostInstanceMsg),        MI_TRUE},
    {enumerateInstancesMessageFields,   sizeof(EnumerateInstancesReq),      MI_FALSE},
    {emptyMessageFields,                sizeof(PostResultMsg),      MI_FALSE},
    {emptyMessageFields,                sizeof(NoOpReq),        MI_FALSE},
    {emptyMessageFields,                sizeof(NoOpRsp),        MI_FALSE},
    {emptyMessageFields,                sizeof(DispResultMsg),      MI_FALSE},
    {invokeMessageFields,               sizeof(InvokeReq),      MI_TRUE},
    {associatorsOfMessageFields,        sizeof(AssociatorsOfReq),       MI_TRUE},
    {referencesOfMessageFields,         sizeof(ReferencesOfReq),        MI_TRUE},
    {subscribeRequestMessageFields,     sizeof(SubscribeReq),       MI_FALSE},
    {subscribeResponseMessageFields,    sizeof(SubscribeRes),       MI_FALSE},
    {deleteInstanceMessageFields,       sizeof(DeleteInstanceReq),      MI_TRUE},
    {createInstanceMessageFields,       sizeof(CreateInstanceReq),      MI_TRUE},
    {modifyInstanceMessageFields,       sizeof(ModifyInstanceReq),      MI_TRUE},
    {binProtocolNotificationFields,     sizeof(BinProtocolNotification),MI_FALSE}
};  
    
/*
**==============================================================================
**
** Public definitions
**
**==============================================================================
*/

Message* __Message_New(
    MessageTag tag,
    size_t structSize,
    MI_Uint64 msgID,
    MI_Uint32 flags)
{
    Batch *batch;
    Message* self;

    batch = Batch_New(BATCH_MAX_PAGES);

    if (!batch)
        return NULL;

    /* Allocate heap space for message */
    self = Batch_Get(batch, structSize);

    if (!self)
        return NULL;

    /* Clear all fields */
    memset(self, 0, structSize);

    /* Set the tag */
    self->tag = tag;

    /* Set the message id and flags */
    self->msgID = msgID;
    self->flags = flags;

    /* ref-counter is set to 1, to balance NewMessage/Release Message pair*/
    self->refCounter = 1;

    /* Copy batch onto message (released by delete method) */
    self->batch = batch;

    return self;
}

/*
    Decrements message's ref-counter and destroys
    mesage if last reference was released
    Parameters:
    self - message to decref/release
*/
void Message_Release(
    Message* self)
{
    if (AtomicDec(&self->refCounter))
    {
        /* Call destructor */
        if (self->dtor)
            (*self->dtor)(self, self->dtorData);

        /* Release linked request */
        if (self->request)
            Message_Release(self->request);

        Batch_Destroy(self->batch);
    }
}

static void _Message_Print(
    const void* msg, 
    FILE* os, 
    const char* structName,
    const Field fields[])
{
    size_t i;

    fprintf(os, "%s\n", structName);
    fprintf(os, "{\n");

    for (i = 0; fields[i].name; i++)
    {
        const Field* f = &fields[i];

        /* Print name */
        fprintf(os, "    %s=", f->name);

        /* Print value */
        switch (f->type)
        {
            case FT_UINT32:
            {
                MessageTag* p = (MessageTag*)((char*)msg + f->off);
                fprintf(os, "%u", *p);
                break;
            }
            case FT_RESULT:
            {
                MI_Result* p = (MI_Result*)((char*)msg + f->off);
                Fzprintf(os, MI_T("%u [%s]"),*p, Result_ToString(*p));

                break;
            }
            case FT_ATOMIC:
            {
                AtomicInt* p = (AtomicInt*)((char*)msg + f->off);
                Fzprintf(os, MI_T("%d"),(int)(*p));

                break;
            }
            case FT_UINT64:
            {
                MI_Uint64* p = (MI_Uint64*)((char*)msg + f->off);
                fprintf(os, UINT64_FMT, *p);
                break;
            }
            case FT_BOOLEAN:
            {
                MI_Boolean* p = (MI_Boolean*)((char*)msg + f->off);
                fprintf(os, "%s", *p ? "TRUE" : "FALSE");
                break;
            }
            case FT_STRING:
            {
                MI_Char** p = (MI_Char**)((char*)msg + f->off);

                if (*p)
                    Fzprintf(os, MI_T("\"%s\""), *p);
                else
                    fprintf(os, "NULL");
                break;
            }
            case FT_STRINGA:
            {
                StringArray** p = (StringArray**)((char*)msg + f->off);

                if (*p)
                    StringArray_Print(*p, os);
                else
                    fprintf(os, "NULL");
                break;
            }
            case FT_INSTANCE:
            {
                MI_Instance** p = (MI_Instance**)((char*)msg + f->off);

                if (*p)
                {
                    fputc('\n', os);
                    MI_Instance_Print(*p, os, 1);
                }
                else
                    fprintf(os, "NULL\n");
                break;
            }
            default:
                break;
        }

        if (f->type != FT_INSTANCE)
            fputc('\n', os);
    }

    fprintf(os, "}\n");
}

void MessagePrint(const Message* msg, FILE* os)
{
    switch ( msg->tag )
    {
        case GetInstanceReqTag:
            {
                const GetInstanceReq* m = (const GetInstanceReq*)msg;
                GetInstanceReq_Print(m, os);
            }
            break;

        case PostInstanceMsgTag:
            {
                const PostInstanceMsg* m = (const PostInstanceMsg*)msg;
                PostInstanceMsg_Print(m, os);
            }
            break;

        case EnumerateInstancesReqTag:
            {
                const EnumerateInstancesReq* m = (const EnumerateInstancesReq*)msg;
                EnumerateInstancesReq_Print(m, os);
            }
            break;

        case PostResultMsgTag:
            {
                const PostResultMsg* m = (const PostResultMsg*)msg;
                PostResultMsg_Print(m, os);
            }
            break;

        case NoOpReqTag:
            {
                const NoOpReq* m = (const NoOpReq*)msg;
                NoOpReq_Print(m, os);
            }
            break;

        case NoOpRspTag:
            {
                const NoOpRsp* m = (const NoOpRsp*)msg;
                NoOpRsp_Print(m, os);
            }
            break;

        case DispResultMsgTag:
            {
                const DispResultMsg* m = (const DispResultMsg*)msg;
                DispResultMsg_Print(m, os);
            }
            break;

        case InvokeReqTag:
            {
                const InvokeReq* m = (const InvokeReq*)msg;
                InvokeReq_Print(m, os);
            }
            break;

        case AssociatorsOfReqTag:
            {
                const AssociatorsOfReq* m = (const AssociatorsOfReq*)msg;
                AssociatorsOfReq_Print(m, os);
            }
            break;

        case ReferencesOfReqTag:
            {
                const ReferencesOfReq* m = (const ReferencesOfReq*)msg;
                ReferencesOfReq_Print(m, os);
            }
            break;

        case SubscribeReqTag:
            {
                const SubscribeReq* m = (const SubscribeReq*)msg;
                SubscribeReq_Print(m, os);
            }
            break;

        case SubscribeResTag:
            {
                const SubscribeRes* m = (const SubscribeRes*)msg;
                SubscribeRes_Print(m, os);
            }
            break;

        case DeleteInstanceReqTag:
            {
                const DeleteInstanceReq* m = (const DeleteInstanceReq*)msg;
                DeleteInstanceReq_Print(m, os);
            }
            break;

        case CreateInstanceReqTag:
            {
                const CreateInstanceReq* m = (const CreateInstanceReq*)msg;
                CreateInstanceReq_Print(m, os);
            }
            break;

        case ModifyInstanceReqTag:
            {
                const ModifyInstanceReq* m = (const ModifyInstanceReq*)msg;
                ModifyInstanceReq_Print(m, os);
            }
            break;

        case BinProtocolNotificationTag:
            {
                const BinProtocolNotification* m = (const BinProtocolNotification*)msg;
                BinProtocolNotification_Print(m, os);
            }
            break;

        default:
            fprintf(os, "unknown message tag %d\n", msg->tag);
            break;

    }
}

/*
**==============================================================================
**
** Field information.
**
**==============================================================================
*/

void GetInstanceReq_Print(const GetInstanceReq* msg, FILE* os)
{
    typedef GetInstanceReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"instanceName", FT_INSTANCE, offsetof(Self, instanceName)},
        {"includeClassOrigin", FT_BOOLEAN, offsetof(Self, includeClassOrigin)},
        {"propertySet", FT_STRINGA, offsetof(Self, propertySet)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "GetInstanceReq", fields);
}

void CreateInstanceReq_Print(const CreateInstanceReq* msg, FILE* os)
{
    typedef CreateInstanceReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"instanceName", FT_INSTANCE, offsetof(Self, instance)},
        {"propertySet", FT_STRINGA, offsetof(Self, propertySet)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "CreateInstanceReq", fields);
}

void ModifyInstanceReq_Print(const ModifyInstanceReq* msg, FILE* os)
{
    typedef ModifyInstanceReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"instanceName", FT_INSTANCE, offsetof(Self, instance)},
        {"propertySet", FT_STRINGA, offsetof(Self, propertySet)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "ModifyInstanceReq", fields);
}

void DeleteInstanceReq_Print(const DeleteInstanceReq* msg, FILE* os)
{
    typedef DeleteInstanceReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"instanceName", FT_INSTANCE, offsetof(Self, instanceName)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "DeleteInstanceReq", fields);
}

void InvokeReq_Print(const InvokeReq* msg, FILE* os)
{
    typedef InvokeReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"nameSpace", FT_STRING, offsetof(Self, nameSpace)},
        {"className", FT_STRING, offsetof(Self, className)},
        {"function", FT_STRING, offsetof(Self, function)},
        {"instance", FT_INSTANCE, offsetof(Self, instance)},
        {"instanceParams", FT_INSTANCE, offsetof(Self, instanceParams)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "InvokeReq", fields);
}

void AssociatorsOfReq_Print(const AssociatorsOfReq* msg, FILE* os)
{
    typedef AssociatorsOfReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"nameSpace", FT_STRING, offsetof(Self, nameSpace)},
        {"assocClass", FT_STRING, offsetof(Self, assocClass)},
        {"resultClass", FT_STRING, offsetof(Self, resultClass)},
        {"role", FT_STRING, offsetof(Self, role)},
        {"resultRole", FT_STRING, offsetof(Self, resultRole)},
        {"instance", FT_INSTANCE, offsetof(Self, instance)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "AssociatorsOfReq", fields);
}

void ReferencesOfReq_Print(const ReferencesOfReq* msg, FILE* os)
{
    typedef ReferencesOfReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"nameSpace", FT_STRING, offsetof(Self, nameSpace)},
        {"assocClass", FT_STRING, offsetof(Self, assocClass)},
        {"role", FT_STRING, offsetof(Self, role)},
        {"instance", FT_INSTANCE, offsetof(Self, instance)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "ReferencesOfReq", fields);
}

void PostInstanceMsg_Print(const PostInstanceMsg* msg, FILE* os)
{
    typedef PostInstanceMsg Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"instance", FT_INSTANCE, offsetof(Self, instance)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "PostInstanceMsg", fields);
}

void PostResultMsg_Print(const PostResultMsg* msg, FILE* os)
{
    typedef PostResultMsg Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"result", FT_RESULT, offsetof(Self, result)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "PostResultMsg", fields);
}

void DispResultMsg_Print(const DispResultMsg* msg, FILE* os)
{
    typedef DispResultMsg Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"result", FT_RESULT, offsetof(Self, result)},
        {"requestCounter", FT_ATOMIC, offsetof(Self, requestCounter)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "DispResultMsg", fields);
}

void EnumerateInstancesReq_Print(
    const EnumerateInstancesReq* msg, 
    FILE* os)
{
    typedef EnumerateInstancesReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"nameSpace", FT_STRING, offsetof(Self, nameSpace)},
        {"className", FT_STRING, offsetof(Self, className)},
        {"requestClassName", FT_STRING, offsetof(Self, requestClassName)},
        {"deepInheritance", FT_BOOLEAN, offsetof(Self, deepInheritance)},
        {"includeClassOrigin", FT_BOOLEAN, offsetof(Self, includeClassOrigin)},
        {"propertySet", FT_STRINGA, offsetof(Self, propertySet)},
        {"queryLanguage", FT_STRING, offsetof(Self, queryLanguage)},
        {"queryExpression", FT_STRING, offsetof(Self, queryExpression)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "EnumerateInstancesReq", fields);
}

void SubscribeReq_Print(const SubscribeReq* msg, FILE* os)
{
    typedef SubscribeReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"nameSpace", FT_STRING, offsetof(Self, nameSpace)},
        {"className", FT_STRING, offsetof(Self, className)},
        {"filter", FT_STRING, offsetof(Self, filter)},
        {"language", FT_STRING, offsetof(Self, language)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "SubscribeReq", fields);
}

void SubscribeRes_Print(const SubscribeRes* msg, FILE* os)
{
    typedef SubscribeRes Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {"subscriptionID", FT_STRING, offsetof(Self, subscriptionID)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "SubscribeRes", fields);
}

void NoOpReq_Print(const NoOpReq* msg, FILE* os)
{
    typedef NoOpReq Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "NoOpReq", fields);
}

void NoOpRsp_Print(const NoOpRsp* msg, FILE* os)
{
    typedef NoOpRsp Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "NoOpRsp", fields);
}

void BinProtocolNotification_Print(const BinProtocolNotification* msg, FILE* os)
{
    typedef BinProtocolNotification Self;
    static const Field fields[] =
    {
        {"tag", FT_UINT32, offsetof(Self, base.tag)},
        {"msgID", FT_UINT64, offsetof(Self, base.msgID)},
        {"clientID", FT_UINT64, offsetof(Self, base.clientID)},
        {NULL, 0, 0},
    };
    _Message_Print(msg, os, "BinProtocolNotification", fields);
}

static MI_Boolean _UnpackInstance(
    Batch* batch,
    void* ptr,
    MI_Uint32 size,
    MI_Instance** instanceOut)
{
    MI_Result r;
    Buf buf = BUF_INITIALIZER;

    /* borrow pointer for unpacking, leaving it in the batch */
    buf.data = ptr;
    buf.size = size;

    r = Instance_Unpack(instanceOut, &buf, batch, MI_FALSE);
    return r == MI_RESULT_OK;
}

static MI_Result _RestoreMessage(
    Message* msg,
    const Header_BatchInfoItem* ptrAdjustmentInfo,
    size_t ptrAdjustmentInfoCount,
    MI_Boolean skipInstanceUnpack,
    const MessageField* messageFields)
{
    char* chunk = (char*)msg;
    Batch* batch = msg->batch;

    while (messageFields->type != MFT_END_OF_LIST)
    {
        void** ptr = (void**)(chunk + messageFields->off);
        switch (messageFields->type)
        {
        case MFT_POINTER_SET_NULL:
            *ptr = 0;
            break;

        case MFT_POINTER_OPT:
        case MFT_POINTER:
            if (*ptr)
            {
                if (!Batch_FixPointer(
                    batch,
                    ptrAdjustmentInfo,
                    ptrAdjustmentInfoCount,
                    ptr))
                        return MI_RESULT_INVALID_PARAMETER;
            }
            else if (messageFields->type == MFT_POINTER)
                return MI_RESULT_INVALID_PARAMETER;

            break;

        case MFT_INSTANCE:
        case MFT_INSTANCE_OPT:
            {
                void** ptrPacked = (void**)(chunk + messageFields->offPackedPtr);
                MI_Uint32 packedSize = * (const MI_Uint32*)(chunk + messageFields->offPackedSize);

                *ptr = 0;

                if (*ptrPacked)
                {
                    if (!Batch_FixPointer(
                        batch,
                        ptrAdjustmentInfo,
                        ptrAdjustmentInfoCount,
                        ptrPacked))
                        return MI_RESULT_INVALID_PARAMETER;

                    if (!skipInstanceUnpack && !_UnpackInstance(
                        batch,
                        *ptrPacked,
                        packedSize,
                        (MI_Instance**)ptr))
                        return MI_RESULT_INVALID_PARAMETER;
                }
                else if (messageFields->type == MFT_INSTANCE)
                    return MI_RESULT_INVALID_PARAMETER;

            }
            
            break;

        default:
            break;
        }

        messageFields++;
    }

    return MI_RESULT_OK;
}

static MI_Result _Clone(
    const Message* msgSrc,
    Message* msg,
    const MessageField* messageFields,
    size_t size)
{
    char* chunk = (char*)msg;
    Batch* batch = msg->batch;
    const char* chunkSrc = (const char*)msgSrc;

    /* copy all primitve data first */
    memcpy(chunk + sizeof(Message), chunkSrc + sizeof(Message), size - sizeof(Message));

    while (messageFields->type != MFT_END_OF_LIST)
    {
        void** ptr = (void**)(chunk + messageFields->off);
        void** ptrSrc = (void**)(chunkSrc + messageFields->off);

        switch (messageFields->type)
        {
        case MFT_POINTER_SET_NULL:
        default:
            break;

        case MFT_POINTER_OPT:
        case MFT_POINTER:
            if (*ptrSrc)
            {
                *ptr = Batch_Strdup2(batch, (const char*)*ptrSrc);

                if (!*ptr)
                    return MI_RESULT_FAILED;
            }
            else if (messageFields->type == MFT_POINTER)
                return MI_RESULT_INVALID_PARAMETER;

            break;

        case MFT_INSTANCE:
        case MFT_INSTANCE_OPT:
            {
                void** ptrPacked = (void**)(chunk + messageFields->offPackedPtr);
                MI_Uint32* packedSize =  (MI_Uint32*)(chunk + messageFields->offPackedSize);
                const void* ptrPackedSrc = *(void**)(chunkSrc + messageFields->offPackedPtr);
                MI_Uint32 packedSizeSrc =  *(MI_Uint32*)(chunkSrc + messageFields->offPackedSize);

                *ptr = 0;

                if (ptrPackedSrc)
                {
                    /* Take existing packed instance if exist (received from binary protocol */
                    *packedSize = packedSizeSrc;
                    *ptrPacked = Batch_Get(batch, packedSizeSrc);

                    if (!*ptrPacked)
                        return MI_RESULT_FAILED;

                    memcpy(*ptrPacked, ptrPackedSrc, packedSizeSrc);
                }
                else if (*ptrSrc)
                {
                    /* Pack instance in binary buffer (received form wsman) */
                    if (MI_RESULT_OK != InstanceToBatch(
                        (const MI_Instance*)(*ptrSrc), 
                        NULL, /* filterProperties */
                        NULL, /* filterPropertiesData */
                        batch, 
                        ptrPacked, packedSize))
                        return MI_RESULT_FAILED;
                }
                else if (messageFields->type == MFT_INSTANCE)
                    /* Return error if non-optional parameter is missing */
                    return MI_RESULT_INVALID_PARAMETER;
            }
            
            break;
        }

        messageFields++;
    }

    return MI_RESULT_OK;
}
MI_Result MessageFromBatch(
    Batch* batch,
    void* originalMsgPtr,
    const Header_BatchInfoItem* ptrAdjustmentInfo,
    size_t ptrAdjustmentInfoCount,
    MI_Boolean skipInstanceUnpack,
    Message** msgOut)
{
    Message* msg = originalMsgPtr;
    MI_Uint32 index;

    if (!Batch_FixPointer(
        batch,
        ptrAdjustmentInfo,
        ptrAdjustmentInfoCount,
        (void*)&msg))
        return MI_RESULT_INVALID_PARAMETER;

    /* fix base part of message */
    msg->batch = batch;
    msg->refCounter = 1;

    if (MI_RESULT_OK != _RestoreMessage(
        msg,
        ptrAdjustmentInfo,
        ptrAdjustmentInfoCount,
        skipInstanceUnpack,
        baseMessageFields))
        return MI_RESULT_INVALID_PARAMETER;

    index = (MI_Uint32)msg->tag;

    if (index >= MI_COUNT(allMessages))
        return MI_RESULT_INVALID_PARAMETER;

    if (MI_RESULT_OK != _RestoreMessage(
        msg,
        ptrAdjustmentInfo,
        ptrAdjustmentInfoCount,
        skipInstanceUnpack,
        allMessages[index].fields))
        return MI_RESULT_INVALID_PARAMETER;

    *msgOut = msg;
    return MI_RESULT_OK;
}

MI_Result MessagePackCloneForBinarySending(
    Message* msgSrc,
    Message** msgOut)
{
    Message* msg = msgSrc;
    MI_Uint32 index;

    index = (MI_Uint32)msg->tag;

    if (index >= MI_COUNT(allMessages))
        return MI_RESULT_INVALID_PARAMETER;

    if (!allMessages[index].cloneRequired)
    {
        *msgOut = msg;
        Message_AddRef(msg);
        return MI_RESULT_OK;
    }

    /* create a copy */
    msg = __Message_New(msgSrc->tag, allMessages[index].size, msgSrc->msgID, msgSrc->flags);

    if (!msg)
        return MI_RESULT_FAILED;

    msg->clientID = msgSrc->clientID;

    if (MI_RESULT_OK != _Clone(msgSrc, msg, allMessages[index].fields, allMessages[index].size))
    {
        Message_Release(msg);
        return MI_RESULT_FAILED;
    }

    *msgOut = msg;
    return MI_RESULT_OK;
}

ViewCVS 0.9.2