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

   1 mike  1.1 /*
   2           **==============================================================================
   3           **
   4           ** Open Management Infrastructure (OMI)
   5           **
   6           ** Copyright (c) Microsoft Corporation
   7           ** 
   8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
   9           ** use this file except in compliance with the License. You may obtain a copy 
  10           ** of the License at 
  11           **
  12           **     http://www.apache.org/licenses/LICENSE-2.0 
  13           **
  14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
  16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
  17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
  18           **
  19           ** See the Apache 2 License for the specific language governing permissions 
  20           ** and limitations under the License.
  21           **
  22 mike  1.1 **==============================================================================
  23           */
  24           
  25           #include <ctype.h>
  26           #include "instance.h"
  27           #include "helpers.h"
  28           #include "naming.h"
  29           #include "indent.h"
  30           #include "types.h"
  31           #include "schemadecl.h"
  32           #include "alloc.h"
  33           #include "field.h"
  34           #include "io.h"
  35           
  36           #if 0
  37           # include "return.h"
  38           #endif
  39           
  40           /*
  41           **==============================================================================
  42           **
  43 mike  1.1 ** Local definitions
  44           **
  45           **==============================================================================
  46           */
  47           
  48           #define T MI_T
  49           
  50           /* Magic number of InstanceHeader */
  51           static MI_Uint32 _MAGIC = 0xB26AEA60;
  52           
  53           /* Number of default pages for a self-owned batch object */
  54           static MI_Uint32 _NUM_PAGES = 8;
  55           
  56           /* The minimum number of reserved properties for a dynamic instance */
  57           static MI_Uint32 _CAPACITY = 32;
  58           
  59           /* Find capacity (lesser of _CAPACITY or x rounded to power of 2) */
  60           static MI_Uint32 _FindCapacity(MI_Uint32 x)
  61           {
  62               if (x <= _CAPACITY)
  63                   return _CAPACITY;
  64 mike  1.1     else
  65               {
  66                   MI_Uint32 r = x - 1;
  67           
  68                   r |= (r >> 1);
  69                   r |= (r >> 2);
  70                   r |= (r >> 4);
  71                   r |= (r >> 8);
  72                   r |= (r >> 16);
  73           
  74                   return r + 1;
  75               }
  76           }
  77           
  78           /* 
  79            * Obtains the self pointer for this instance. For static instances, this
  80            * it is the same as the instance parameter. For dynamic instances, the
  81            * self pointer is given by instance->self.
  82            */
  83           MI_INLINE Instance* _SelfOf(const MI_Instance* instance)
  84           {
  85 mike  1.1     Instance* self = (Instance*)instance;
  86           
  87               if (self)
  88               {
  89                   if (self->self)
  90                       self = self->self;
  91           
  92                   return self;
  93               }
  94           
  95               DEBUG_ASSERT(0);
  96               return NULL;
  97           }
  98           
  99           /* Return the index of the given property or (MI_Uin32)-1 if not found */
 100           static MI_Uint32 _FindPropertyDecl(
 101               const MI_ClassDecl* cd,
 102               const MI_Char* name)
 103           {
 104               MI_PropertyDecl** start = cd->properties;
 105               MI_PropertyDecl** end = start + cd->numProperties;
 106 mike  1.1     MI_PropertyDecl** p = start;
 107               MI_Uint32 code;
 108           
 109               code = Hash(name);
 110           
 111               while (p != end) 
 112               {
 113                   if ((*p)->code == code && Zcasecmp((*p)->name, name) == 0)
 114                       return (MI_Uint32)(p - start);
 115                   p++;
 116               }
 117           
 118               return (MI_Uint32)-1;
 119           }
 120           
 121 mike  1.2 static MI_PropertyDecl* _LookupPropertyDecl(
 122               const MI_ClassDecl* cd,
 123               const MI_Char* name)
 124           {
 125               MI_Uint32 index = _FindPropertyDecl(cd, name);
 126           
 127               if (index == (MI_Uint32)-1)
 128                   return NULL;
 129           
 130               return cd->properties[index];
 131           }
 132           
 133 mike  1.1 static MI_PropertyDecl* _ClonePropertyDecl(
 134               const MI_PropertyDecl* pd,
 135               Batch* batch)
 136           {
 137               MI_PropertyDecl* p;
 138           
 139               p = (MI_PropertyDecl*)BCalloc(batch, sizeof(MI_PropertyDecl), CALLSITE);
 140           
 141               if (!p)
 142                   return NULL;
 143           
 144               if (pd->name)
 145               {
 146                   p->name = BStrdup(batch, pd->name, CALLSITE);
 147                   if (!p->name)
 148                       return NULL;
 149               }
 150           
 151               p->flags = pd->flags;
 152               p->code = pd->code;
 153               p->type = pd->type;
 154 mike  1.1     p->offset = pd->offset;
 155           
 156               return p;
 157           }
 158           
 159           static MI_PropertyDecl** _ClonePropertyDecls(
 160               MI_PropertyDecl** properties,
 161               MI_Uint32 size,
 162               Batch* batch)
 163           {
 164               MI_PropertyDecl** data;
 165               MI_Uint32 i;
 166           
 167               /* Allocate at least _CAPACITY properties */
 168               MI_Uint32 cap = (size < _CAPACITY) ? _CAPACITY : size;
 169           
 170               /* Allocate properties array */
 171               data = (MI_PropertyDecl**)BAlloc(batch, sizeof(MI_PropertyDecl*) * cap,
 172                   CALLSITE);
 173               if (!data)
 174                   return NULL;
 175 mike  1.1 
 176               /* Copy each property */
 177               for (i = 0; i < size; i++)
 178               {
 179                   MI_PropertyDecl* pd = _ClonePropertyDecl(properties[i], batch);
 180                   if (!pd)
 181                       return NULL;
 182           
 183                   data[i] = pd;
 184               }
 185           
 186               return data;
 187           }
 188           
 189           static MI_ClassDecl* _CloneClassDecl(
 190               const MI_ClassDecl* cd,
 191               Batch* batch)
 192           {
 193               MI_ClassDecl* p;
 194           
 195               /* Instance.classDecl */
 196 mike  1.1     p = (MI_ClassDecl*)BCalloc(batch, sizeof(MI_ClassDecl), CALLSITE);
 197               if (!p)
 198                   return NULL;
 199           
 200               /* Instance.name */
 201               if (cd->name)
 202               {
 203                   p->name = BStrdup(batch, cd->name, CALLSITE);
 204                   if (!p->name)
 205                       return NULL;
 206               }
 207           
 208               /* Instance.size */
 209               p->size = cd->size;
 210           
 211               /* Instance.properties */
 212               {
 213                   p->properties = _ClonePropertyDecls(cd->properties, cd->numProperties, 
 214                       batch);
 215           
 216                   if (!p->properties)
 217 mike  1.1             return NULL;
 218           
 219                   p->numProperties = cd->numProperties;
 220               }
 221           
 222               return p;
 223           }
 224           
 225           MI_INLINE InstanceHeader* _HeaderOf(Instance* self)
 226           {
 227               return self ? ((InstanceHeader*)self - 1) : NULL;
 228           }
 229           
 230           MI_INLINE Instance* _InstanceOf(InstanceHeader* self)
 231           {
 232               return self ? (Instance*)(self + 1) : NULL;
 233           }
 234           
 235           static Instance* _AllocInstance(Batch* batch, size_t size)
 236           {
 237               InstanceHeader* h = (InstanceHeader*)BCalloc(
 238 mike  1.1         batch, 
 239                   sizeof(InstanceHeader) + size, 
 240                   CALLSITE);
 241           
 242               if (!h)
 243                   return NULL;
 244           
 245               h->magic = _MAGIC;
 246               h->u.refs = 1;
 247               return _InstanceOf(h);
 248           }
 249           
 250           static Instance* _ReallocInstance(
 251               Batch* batch, 
 252               Instance* self, 
 253               size_t oldSize, 
 254               size_t newSize)
 255           {
 256               InstanceHeader* h = (InstanceHeader*)BRealloc(
 257                   batch, 
 258                   _HeaderOf(self), 
 259 mike  1.1         sizeof(InstanceHeader) + oldSize,
 260                   sizeof(InstanceHeader) + newSize,
 261                   CALLSITE);
 262           
 263               if (!h)
 264                   return NULL;
 265           
 266               h->magic = _MAGIC;
 267               h->u.refs = 1;
 268           
 269               return _InstanceOf(h);
 270           }
 271           
 272           static void _FreeInstance(
 273               Batch* batch, 
 274               Instance* self)
 275           {
 276               InstanceHeader* h = _HeaderOf(self);
 277           
 278               if (h)
 279               {
 280 mike  1.1         DEBUG_ASSERT(h->magic == _MAGIC);
 281           #if defined(CONFIG_ENABLE_DEBUG)
 282                   memset(h, 0xDD, sizeof(InstanceHeader) + sizeof(Instance));
 283           #endif
 284                   BFree(batch, h, CALLSITE);
 285               }
 286           }
 287           
 288           /*
 289            * Each dynamic instance is 'wrapped' inside another instance (referred to
 290            * by the self field). This requiredment is imposed by the 
 291            * MI_Instance_AddElement() function, which does not allow the address of
 292            * the instance to change. Hence, indirection is required to allow the inner
 293            * instance to be relocated in memory as new properties are added. The 
 294            * resulting layout is depicted below.
 295            * 
 296            *        (Wrapper)
 297            *     +-------------+
 298            *     | MI_Instance |
 299            *     +---------+---+
 300            *     |         |   |         (Inner)
 301 mike  1.1  *     +---------+---+     +-------------+
 302            *     | self    | ------> | MI_Instance |
 303            *     +---------+---+     +---------+---+
 304            *                         |         |   |
 305            *                         +---------+---+
 306            *                         |         |   |
 307            *                         +---------+---+
 308            *
 309            * All methods of the instance type, must resolve the self pointer using
 310            * _SelfOf(), which either returns the sole parameter itself (for static 
 311            * instances) or the self field (for dynamic instances).
 312            *
 313            */
 314           static Instance* _WrapInstance(
 315               Instance* self, 
 316               Batch* batch)
 317           {
 318               Instance* wrapper;
 319           
 320               if (!self)
 321                   return NULL;
 322 mike  1.1 
 323               /* Allocate space for outer wrapper instance */
 324               wrapper = (Instance*)_AllocInstance(batch, sizeof(MI_Instance));
 325               if (!wrapper)
 326                   return NULL;
 327           
 328               /* Copy fields from inner instance to outer instance */
 329               *wrapper = *self;
 330           
 331               /* Set outer instance self to point to inner instance */
 332               wrapper->self = self;
 333           
 334               return wrapper;
 335           }
 336           
 337           MI_Uint32 _CountKeys(
 338               const Instance* self)
 339           {
 340               MI_Uint32 n = 0;
 341               const MI_ClassDecl* cd = self->classDecl;
 342               MI_Uint32 i;
 343 mike  1.1 
 344               for (i = 0; i < cd->numProperties; i++)
 345               {
 346                   if (cd->properties[i]->flags & MI_FLAG_KEY)
 347                       n++;
 348               }
 349           
 350               return n;
 351           }
 352           
 353           /*
 354           **==============================================================================
 355           **
 356           ** Public definitions
 357           **
 358           **==============================================================================
 359           */
 360           
 361           MI_Result MI_CALL Instance_Construct(
 362               MI_Instance* self_,
 363               const MI_ClassDecl* classDecl,
 364 mike  1.1     Batch* batch_)
 365           {
 366               Instance* self = (Instance*)self_;
 367               MI_ClassDecl* cd = (MI_ClassDecl*)classDecl;
 368               Batch* batch = batch_;
 369           
 370               /* Check for null arguments */
 371               if (!self || !cd)
 372                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 373           
 374               /* Create a new batch */
 375               if (!batch)
 376               {
 377                   batch = Batch_New(_NUM_PAGES);
 378                   if (!batch)
 379                       return MI_RESULT_FAILED;
 380               }
 381           
 382               /* Zero-fill the object */
 383               memset(self, 0, cd->size);
 384           
 385 mike  1.1     /* MI_Instance.ft */
 386               self->ft = &__mi_instanceFT;
 387           
 388               /* MI_Instance.self */
 389               self->self = self;
 390           
 391               /* MI_Instance.classDecl */
 392               self->classDecl = cd;
 393           
 394               /* MI_Instance.batch */
 395               self->batch = batch;
 396           
 397               /* Flags */
 398               self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
 399           
 400               MI_RETURN(MI_RESULT_OK);
 401           }
 402           
 403           MI_Result Instance_New(
 404               MI_Instance** selfOut,
 405               const MI_ClassDecl* classDecl,
 406 mike  1.1     Batch* batch_)
 407           {
 408               Instance* self;
 409               Batch* batch = batch_;
 410               MI_Result r;
 411           
 412               /* Check for null arguments */
 413               if (!selfOut || !classDecl || !batch)
 414                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 415           
 416               /* Null out selfOut */
 417               *selfOut = NULL;
 418           
 419               /* Create a new batch */
 420               if (!batch)
 421               {
 422                   batch = Batch_New(_NUM_PAGES);
 423                   if (!batch)
 424                       return MI_RESULT_FAILED;
 425               }
 426           
 427 mike  1.1     /* Allocate structure */
 428               self = _AllocInstance(batch, classDecl->size);
 429               if (!self)
 430               {
 431                   r = MI_RESULT_FAILED;
 432                   goto failed;
 433               }
 434           
 435               /* Initialize the object */
 436               r = Instance_Construct((MI_Instance*)self, classDecl, batch);
 437               if (r != MI_RESULT_OK)
 438                   goto failed;
 439           
 440               /* Arrange to release batch if we created it */
 441               self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
 442           
 443               *selfOut = (MI_Instance*)self;
 444               MI_RETURN(MI_RESULT_OK);
 445           
 446           failed:
 447               if (batch != batch_)
 448 mike  1.1         Batch_Delete(batch);
 449               return r;
 450           }
 451           
 452           MI_Result MI_CALL Instance_InitConvert(
 453               MI_Instance* self_,
 454               const MI_ClassDecl* cd1,
 455               const MI_Instance* inst_,
 456               MI_Boolean keysOnly,
 457               MI_Boolean allowKeylessInst,
 458               MI_Boolean copy,
 459               Batch* batch_)
 460           {
 461               Instance* self;
 462               const Instance* inst = _SelfOf(inst_);
 463               MI_Uint32 i;
 464               MI_Result r;
 465               const MI_ClassDecl* cd2;
 466               const MI_SchemaDecl* sd1;
 467               Batch* batch = batch_;
 468           
 469 mike  1.1     /* Resolve the schema declaration (based on type) */
 470               if (cd1->flags & MI_FLAG_METHOD)
 471                   sd1 = ((MI_MethodDecl*)cd1)->schema;
 472               else if (cd1->flags & MI_FLAG_CLASS)
 473                   sd1 = cd1->schema;
 474               else
 475 mike  1.2     {
 476 mike  1.1         return MI_RESULT_FAILED;
 477 mike  1.2     }
 478 mike  1.1 
 479               /* Check parameters */
 480               if (!self_ || !cd1 || !inst || !batch)
 481                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 482           
 483               /* Create a new batch */
 484               if (!batch)
 485               {
 486                   batch = Batch_New(_NUM_PAGES);
 487                   if (!batch)
 488 mike  1.2         {
 489 mike  1.1             return MI_RESULT_FAILED;
 490 mike  1.2         }
 491 mike  1.1     }
 492           
 493               cd2 = inst->classDecl;
 494           
 495               /* Initialize the instance */
 496               r = Instance_Construct(self_, cd1, batch);
 497               if (r != MI_RESULT_OK)
 498 mike  1.2     {
 499 mike  1.1         goto failed;
 500 mike  1.2     }
 501 mike  1.1 
 502               /* Get the self pointer from the newly initialized instance */
 503               self = _SelfOf(self_);
 504           
 505               /* Arrange to release the batch */
 506               self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
 507           
 508               /* Copy the nameSpace */
 509               if (inst->nameSpace)
 510               {
 511                   self->nameSpace = BStrdup(batch, inst->nameSpace, CALLSITE);
 512                   if (!self->nameSpace)
 513                   {
 514                       r = MI_RESULT_FAILED;
 515                       goto failed;
 516                   }
 517               }
 518           
 519               /* Copy the serverName */
 520               if (inst->serverName)
 521               {
 522 mike  1.1         self->serverName = BStrdup(batch, inst->serverName, CALLSITE);
 523                   if (!self->serverName)
 524                   {
 525                       r = MI_RESULT_FAILED;
 526                       goto failed;
 527                   }
 528               }
 529           
 530               /* Validate that the two instances share the same key structure */
 531               if (!allowKeylessInst)
 532               {
 533                   for (i = 0; i < cd1->numProperties; i++)
 534                   {
 535                       const MI_PropertyDecl* pd1 = cd1->properties[i];
 536           
 537                       if (pd1->flags & MI_FLAG_KEY)
 538                       {
 539                           MI_Uint32 index;
 540           
 541                           index = _FindPropertyDecl(cd2, pd1->name);
 542                           if (index == (MI_Uint32)-1)
 543 mike  1.1                 {
 544                               r = MI_RESULT_TYPE_MISMATCH;
 545                               goto failed;
 546                           }
 547                       }
 548                   }
 549           
 550                   for (i = 0; i < cd2->numProperties; i++)
 551                   {
 552                       const MI_PropertyDecl* pd2 = cd2->properties[i];
 553           
 554                       if (pd2->flags & MI_FLAG_KEY)
 555                       {
 556                           MI_Uint32 index;
 557           
 558                           index = _FindPropertyDecl(cd1, pd2->name);
 559                           if (index == (MI_Uint32)-1)
 560                           {
 561                               r = MI_RESULT_TYPE_MISMATCH;
 562                               goto failed;
 563                           }
 564 mike  1.1             }
 565                   }
 566               }
 567           
 568               /* ATTN: ignore unknown properties? */
 569           
 570               /* Set non-null properties */
 571               for (i = 0; i < cd2->numProperties; i++)
 572               {
 573                   const MI_PropertyDecl* pd2 = cd2->properties[i];
 574                   Field* field = (Field*)((char*)inst + pd2->offset);
 575           
 576                   /* If requested, ignore non-keys */
 577                   if (keysOnly && !(pd2->flags & MI_FLAG_KEY))
 578                       continue;
 579           
 580                   /* Set the non-null key values */
 581                   if (Field_GetExists(field, pd2->type))
 582                   {
 583                       if (pd2->type == MI_STRING)
 584                       {
 585 mike  1.1                 r = Instance_SetElementFromString(self_, pd2->name,
 586                               ((MI_Value*)field)->string);
 587           
 588                           if (r != MI_RESULT_OK)
 589                           {
 590                               r = MI_RESULT_TYPE_MISMATCH;
 591                               goto failed;
 592                           }
 593                       }
 594                       else if (pd2->type == MI_STRINGA)
 595                       {
 596                           r = Instance_SetElementFromStringA(self_, pd2->name,
 597                               (const MI_Char**)((MI_Value*)field)->stringa.data,
 598                               ((MI_Value*)field)->stringa.size);
 599           
 600                           if (r != MI_RESULT_OK)
 601                           {
 602                               r = MI_RESULT_TYPE_MISMATCH;
 603                               goto failed;
 604                           }
 605                       }
 606 mike  1.1             else if (pd2->type == MI_INSTANCE || pd2->type == MI_REFERENCE)
 607                       {
 608                           MI_Instance* tmpInst;
 609                           MI_ClassDecl* tmpCd;
 610 mike  1.2                 MI_Type type;
 611 mike  1.1 
 612                           /* Find the class declaration in the schema */
 613                           tmpCd = SchemaDecl_FindClassDecl(sd1, 
 614                               _SelfOf(((MI_Value*)field)->instance)->classDecl->name);
 615           
 616                           if (!tmpCd)
 617                           {
 618                               r = MI_RESULT_FAILED;
 619                               goto failed;
 620                           }
 621           
 622                           /* Allocate static instance of this class */
 623                           if (Instance_New(&tmpInst, tmpCd, batch) != MI_RESULT_OK)
 624                           {
 625                               r = MI_RESULT_FAILED;
 626                               goto failed;
 627                           }
 628           
 629                           /* Convert instance */
 630                           r = Instance_InitConvert(tmpInst, tmpCd,
 631                               ((MI_Value*)field)->instance, keysOnly, MI_FALSE, copy, 
 632 mike  1.1                     ((Instance*)tmpInst)->batch);
 633           
 634                           if (r != MI_RESULT_OK)
 635                           {
 636                               __MI_Instance_Delete(tmpInst);
 637                               r = MI_RESULT_TYPE_MISMATCH;
 638                               goto failed;
 639                           }
 640           
 641 mike  1.2                 /* Get the target property type */
 642 mike  1.1                 {
 643 mike  1.2                     MI_PropertyDecl* pd = _LookupPropertyDecl(cd1, pd2->name);
 644 mike  1.1 
 645 mike  1.2                     if (!pd)
 646 mike  1.1                     {
 647 mike  1.2                         r = MI_RESULT_NO_SUCH_PROPERTY;
 648 mike  1.1                         goto failed;
 649                               }
 650           
 651 mike  1.2                     type = pd->type;
 652                           }
 653           
 654                           /* Reject if not instance or reference */
 655 mike  1.1 
 656 mike  1.2                 switch (type)
 657                           {
 658                               case MI_INSTANCE:
 659                               case MI_REFERENCE:
 660                               {
 661                                   MI_Value v;
 662                                   v.instance = tmpInst;
 663 mike  1.1 
 664 mike  1.2                         r = __MI_Instance_SetElement(
 665                                       self_, 
 666                                       pd2->name, 
 667                                       &v, 
 668                                       type,
 669                                       MI_FLAG_ADOPT);
 670           
 671                                   break;
 672                               }
 673                               case MI_INSTANCEA:
 674                               case MI_REFERENCEA:
 675                               {
 676                                   MI_Value v;
 677                                   v.instancea.size = 1;
 678                                   v.instancea.data = 
 679                                       BAlloc(batch, sizeof(void*), CALLSITE);
 680           
 681                                   if (!v.instancea.data)
 682                                   {
 683                                       __MI_Instance_Delete(tmpInst);
 684                                       r = MI_RESULT_FAILED;
 685 mike  1.2                             goto failed;
 686                                   }
 687           
 688                                   v.instancea.data[0] = tmpInst;
 689           
 690                                   r = __MI_Instance_SetElement(
 691                                       self_, 
 692                                       pd2->name, 
 693                                       &v, 
 694                                       type,
 695                                       MI_FLAG_ADOPT);
 696           
 697                                   break;
 698                               }
 699                               default:
 700                               {
 701                                   r = MI_RESULT_TYPE_MISMATCH;
 702                                   break;
 703                               }
 704 mike  1.1                 }
 705           
 706                           if (r != MI_RESULT_OK)
 707                           {
 708                               __MI_Instance_Delete(tmpInst);
 709                               r = MI_RESULT_TYPE_MISMATCH;
 710                               goto failed;
 711                           }
 712                       }
 713                       else if (pd2->type == MI_INSTANCEA || pd2->type == MI_REFERENCEA)
 714                       {
 715                           MI_Value v;
 716                           MI_Uint32 j;
 717           
 718                           v.instancea.size = ((MI_Value*)field)->instancea.size;
 719                           v.instancea.data = BAlloc(batch, 
 720                               v.instancea.size * sizeof(void*), CALLSITE);
 721           
 722                           if (!v.instancea.data)
 723                           {
 724                               r = MI_RESULT_FAILED;
 725 mike  1.1                     goto failed;
 726                           }
 727                           
 728                           for (j = 0; j < v.instancea.size; j++)
 729                           {
 730                               MI_Instance* tmpInst;
 731                               MI_ClassDecl* tmpCd;
 732           
 733                               /* Find the schema declaration */
 734                               tmpCd = SchemaDecl_FindClassDecl(sd1, _SelfOf(((
 735                                   MI_Value*)field)->instancea.data[j])->classDecl->name);
 736           
 737                               if (!tmpCd)
 738                               {
 739                                   r = MI_RESULT_FAILED;
 740                                   goto failed;
 741                               }
 742           
 743                               /* Allocate the instance for the provider */
 744                               if (Instance_New(&tmpInst,tmpCd,batch) != MI_RESULT_OK)
 745                               {
 746 mike  1.1                         r = MI_RESULT_FAILED;
 747                                   goto failed;
 748                               }
 749           
 750                               r = Instance_InitConvert(tmpInst, tmpCd,
 751                                   ((MI_Value*)field)->instancea.data[j], keysOnly, MI_FALSE, copy, 
 752                                   ((Instance*)tmpInst)->batch);
 753           
 754                               if (r != MI_RESULT_OK)
 755                               {
 756                                   MI_Uint32 k;
 757           
 758                                   for (k = 0; k < j; k++)
 759                                       __MI_Instance_Delete(v.instancea.data[k]);
 760           
 761                                   r = MI_RESULT_TYPE_MISMATCH;
 762                                   goto failed;
 763                               }
 764           
 765                               v.instancea.data[j] = tmpInst;
 766                           }
 767 mike  1.1 
 768                           /* Set the value */
 769                           r = __MI_Instance_SetElement(self_, pd2->name, &v, pd2->type,
 770                               MI_FLAG_ADOPT);
 771           
 772                           if (r != MI_RESULT_OK)
 773                           {
 774                               for (j = 0; j < v.instancea.size; j++)
 775                                   __MI_Instance_Delete(v.instancea.data[j]);
 776           
 777                               r = MI_RESULT_TYPE_MISMATCH;
 778                               goto failed;
 779                           }
 780                       }
 781                       else
 782                       {
 783                           MI_Uint32 tmpFlags = copy ? 0 : MI_FLAG_BORROW;
 784           
 785                           /* Set the value */
 786                           r = __MI_Instance_SetElement(self_, pd2->name, (MI_Value*)field,
 787                               pd2->type, tmpFlags);
 788 mike  1.1 
 789                           if (r != MI_RESULT_OK)
 790                           {
 791                               r = MI_RESULT_TYPE_MISMATCH;
 792                               goto failed;
 793                           }
 794                       }
 795                   }
 796               }
 797           
 798           failed:
 799               if (batch != batch_)
 800                   Batch_Delete(batch);
 801               return r;
 802           }
 803           
 804           MI_Result MI_CALL Instance_Clone(
 805               const MI_Instance* self_, 
 806               MI_Instance** instOut,
 807               Batch* batch_)
 808           {
 809 mike  1.1     const Instance* self = _SelfOf(self_);
 810               Batch* batch = batch_;
 811               Instance* inst;
 812               MI_Uint32 i;
 813               MI_Result r;
 814           
 815               /* Check for a null parameter */
 816               if (!self || !instOut)
 817               {
 818                   r = MI_RESULT_FAILED;
 819                   goto failed;
 820               }
 821           
 822               /* Create new batch? */
 823               if (!batch)
 824               {
 825                   batch = Batch_New(_NUM_PAGES);
 826                   if (!batch)
 827                       return MI_RESULT_FAILED;
 828               }
 829           
 830 mike  1.1     /* Allocate the new instance */
 831               {
 832                   MI_Uint32 cap = sizeof(MI_Instance) + _CAPACITY * sizeof(Field);
 833           
 834                   if (self->classDecl->size > cap)
 835                       cap = self->classDecl->size;
 836           
 837                   inst = _AllocInstance(batch, cap);
 838                   if (!inst)
 839                   {
 840                       r = MI_RESULT_FAILED;
 841                       goto failed;
 842                   }
 843               }
 844           
 845               /* Instance.self */
 846               inst->self = inst;
 847           
 848               /* Instance.flags */
 849               if (batch != batch_)
 850               {
 851 mike  1.1         inst->releaseBatch = MI_TRUE;
 852               }
 853           
 854               /* Set Instance.batch */
 855               inst->batch = batch;
 856           
 857               /* Set MI_Instance.ft */
 858               inst->ft = &__mi_instanceFT;
 859           
 860               /* Instance.nameSpace */
 861               if (self->nameSpace)
 862               {
 863                   inst->nameSpace = BStrdup(batch, self->nameSpace, CALLSITE);
 864           
 865                   if (!inst->nameSpace)
 866                   {
 867                       r = MI_RESULT_FAILED;
 868                       goto failed;
 869                   }
 870               }
 871           
 872 mike  1.1     /* Instance.serverName */
 873               if (self->serverName)
 874               {
 875                   inst->serverName = BStrdup(batch, self->serverName, CALLSITE);
 876           
 877                   if (!inst->serverName)
 878                   {
 879                       r = MI_RESULT_FAILED;
 880                       goto failed;
 881                   }
 882               }
 883           
 884               /* Set Instance.classDecl */
 885               if ((void*)self != (void*)self_)
 886               {
 887                   inst->classDecl = _CloneClassDecl(self->classDecl, batch);
 888           
 889                   if (!inst->classDecl)
 890                   {
 891                       r = MI_RESULT_FAILED;
 892                       goto failed;
 893 mike  1.1         }
 894               }
 895               else
 896                   inst->classDecl = self->classDecl;
 897           
 898               /* Clone each of the fields */
 899               for (i = 0; i < self->classDecl->numProperties; i++)
 900               {
 901                   const MI_PropertyDecl* pd = self->classDecl->properties[i];
 902           
 903                   r = Field_Copy(
 904                       (Field*)((char*)inst + pd->offset),
 905                       pd->type,
 906                       (Field*)((char*)self + pd->offset),
 907                       batch);
 908           
 909                   if (r != MI_RESULT_OK)
 910                   {
 911                       r = MI_RESULT_FAILED;
 912                       goto failed;
 913                   }
 914 mike  1.1     }
 915           
 916               /* Wrapper dynamic instances */
 917               if ((void*)self != (void*)self_)
 918               {
 919                   inst = _WrapInstance(inst, batch);
 920                   if (!inst)
 921                   {
 922                       r = MI_RESULT_FAILED;
 923                       goto failed;
 924                   }
 925               }
 926           
 927               *instOut = (MI_Instance*)inst;
 928               return MI_RESULT_OK;
 929           
 930           failed:
 931               if (batch != batch_)
 932                   Batch_Delete(batch);
 933               return r;
 934           }
 935 mike  1.1 
 936           MI_Result MI_CALL Instance_SetClassName(
 937               MI_Instance* self_, 
 938               const MI_Char* className)
 939           {
 940               Instance* self = _SelfOf(self_);
 941               MI_Char* oldClassName;
 942           
 943               /* Check parameters */
 944               if (!self || !className)
 945                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 946           
 947               /* Save old className */
 948               oldClassName = self->classDecl->name;
 949           
 950               /* Set new className */
 951               {
 952                   MI_Char* tmp = BStrdup(self->batch, className, CALLSITE);
 953           
 954                   if (!tmp)
 955                       MI_RETURN(MI_RESULT_FAILED);
 956 mike  1.1 
 957                   self->classDecl->name = tmp;
 958               }
 959           
 960               /* Free old className */
 961               if (oldClassName)
 962                   BFree(self->batch, oldClassName, CALLSITE);
 963           
 964               MI_RETURN(MI_RESULT_OK);
 965           }
 966           
 967           MI_Result MI_CALL Instance_NewDynamic(
 968               MI_Instance** selfOut,
 969               const MI_Char* className,
 970               MI_Uint32 metaType,
 971               Batch* batch_)
 972           {
 973               Instance* self = NULL;
 974               Batch* batch = batch_;
 975               MI_Result r;
 976           
 977 mike  1.1     /* Reject null arguments */
 978               if (!selfOut || !className)
 979                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 980           
 981               /* Null output self pointer */
 982               *selfOut = NULL;
 983           
 984               /* Create batch if necessary */
 985               if (!batch)
 986               {
 987                   batch = Batch_New(_NUM_PAGES);
 988                   if (!batch)
 989                       return MI_RESULT_FAILED;
 990               }
 991           
 992               /* Check that 'className' parameter is a legal CIM className */
 993               if (!LegalName(className))
 994               {
 995                   r = MI_RESULT_INVALID_PARAMETER;
 996                   goto failed;
 997               }
 998 mike  1.1 
 999               /* Allocate instance and reserve room for properties */
1000               {
1001                   self = _AllocInstance(batch, 
1002                       sizeof(MI_Instance) + _CAPACITY * sizeof(Field));
1003           
1004                   if (!self)
1005                   {
1006                       r = MI_RESULT_FAILED;
1007                       goto failed;
1008                   }
1009           
1010                   self->self = self;
1011               }
1012           
1013               /* Set Instance.classDecl */
1014               {
1015                   MI_ClassDecl* cd;
1016           
1017                   /* Allocate and set Instance.classDecl */
1018                   {
1019 mike  1.1             cd = (MI_ClassDecl*)BCalloc(batch, sizeof(MI_ClassDecl), CALLSITE);
1020           
1021                       if (!cd)
1022                       {
1023                           r = MI_RESULT_FAILED;
1024                           goto failed;
1025                       }
1026           
1027                       self->classDecl = cd;
1028                   }
1029                   
1030                   /* MI_ClassDecl.flags: */
1031                   if (metaType & MI_FLAG_ASSOCIATION)
1032                       cd->flags |= MI_FLAG_ASSOCIATION;
1033                   else if (metaType & MI_FLAG_INDICATION)
1034                       cd->flags |= MI_FLAG_INDICATION;
1035                   else if (metaType & MI_FLAG_METHOD)
1036                       cd->flags |= MI_FLAG_METHOD;
1037                   else if (metaType & MI_FLAG_CLASS)
1038                       cd->flags |= MI_FLAG_CLASS;
1039                   else
1040 mike  1.1             cd->flags |= MI_FLAG_CLASS;
1041           
1042                   /* MI_ClassDecl.name: */
1043                   {
1044                       cd->name = BStrdup(batch, className, CALLSITE);
1045           
1046                       if (!cd->name)
1047                       {
1048                           r = MI_RESULT_FAILED;
1049                           goto failed;
1050                       }
1051                   }
1052           
1053                   /* MI_ClassDecl.code: */
1054                   cd->code = Hash(className);
1055           
1056                   /* MI_ClassDecl.properties: */
1057                   {
1058                       MI_PropertyDecl** data;
1059           
1060                       data = (MI_PropertyDecl**)BAlloc(batch,
1061 mike  1.1                 _CAPACITY * sizeof(MI_PropertyDecl), CALLSITE);
1062           
1063                       if (!data)
1064                       {
1065                           r = MI_RESULT_FAILED;
1066                           goto failed;
1067                       }
1068           
1069                       cd->properties = data;
1070                       cd->numProperties = 0;
1071                   }
1072           
1073                   /* MI_ClassDecl.size: */
1074                   cd->size = sizeof(MI_Instance);
1075               }
1076           
1077               /* Set batch: */
1078               self->batch = batch;
1079           
1080               /* Set flags */
1081               if (batch_)
1082 mike  1.1         self->releaseBatch = MI_FALSE;
1083               else
1084                   self->releaseBatch = MI_TRUE;
1085           
1086               /* Set MI_Instance.ft: */
1087               self->ft = &__mi_instanceFT;
1088           
1089               /* Set the self pointer */
1090               self->self = self;
1091           
1092               /* Set output instance (creating a wrapper for it) */
1093               self = _WrapInstance(self, batch);
1094               if (!self)
1095               {
1096                   r = MI_RESULT_FAILED;
1097                   goto failed;
1098               }
1099           
1100               *selfOut = (MI_Instance*)self;
1101               MI_RETURN(MI_RESULT_OK);
1102           
1103 mike  1.1 failed:
1104               if (batch != batch_)
1105                   Batch_Delete(batch);
1106               return r;
1107           }
1108           
1109           MI_Boolean Instance_MatchKeys(
1110               const MI_Instance* self_,
1111               const MI_Instance* inst_)
1112           {
1113               Instance* self;
1114               Instance* inst;
1115           
1116               /* Check parameters */
1117               if (!self_ || !inst_)
1118               {
1119                   return MI_FALSE;
1120               }
1121           
1122               self = _SelfOf(self_);
1123               inst = _SelfOf(inst_);
1124 mike  1.1 
1125               /* Check parameters */
1126               if (!self || !inst)
1127               {
1128                   return MI_FALSE;
1129               }
1130           
1131               /* Verify they have the same number of keys (one or more) */
1132               {
1133                   MI_Uint32 n = _CountKeys(self);
1134           
1135                   if (n == 0 || n != _CountKeys(inst))
1136                   {
1137                       return MI_FALSE;
1138                   }
1139               }
1140           
1141               /* Verify that key fields are identical */
1142               {
1143                   const MI_ClassDecl* cd1 = self->classDecl;
1144                   const MI_ClassDecl* cd2 = inst->classDecl;
1145 mike  1.1         MI_Uint32 i;
1146           
1147                   for (i = 0; i < cd1->numProperties; i++)
1148                   {
1149                       const MI_PropertyDecl* pd1 = cd1->properties[i];
1150                       const MI_PropertyDecl* pd2;
1151                       Field* f1;
1152                       Field* f2;
1153                       MI_Uint32 index;
1154           
1155                       if (pd1->flags & MI_FLAG_KEY)
1156                       {
1157                           index = _FindPropertyDecl(cd2, pd1->name);
1158           
1159                           if (index == (MI_Uint32)-1)
1160                           {
1161                               return MI_FALSE;
1162                           }
1163           
1164                           pd2 = cd2->properties[index];
1165           
1166 mike  1.1                 if (!(pd2->flags & MI_FLAG_KEY))
1167                           {
1168                               return MI_FALSE;
1169                           }
1170           
1171                           if (pd1->type != pd2->type)
1172                               return MI_FALSE;
1173           
1174                           f1 = (Field*)((char*)self + pd1->offset);
1175                           f2 = (Field*)((char*)inst + pd2->offset);
1176           
1177                           if (!Field_MatchKey(f1, f2, pd1->type))
1178                           {
1179                               return MI_FALSE;
1180                           }
1181                       }
1182                   }
1183               }
1184           
1185               return MI_TRUE;
1186           }
1187 mike  1.1 
1188           /*
1189           **==============================================================================
1190           **
1191           ** MI_Instance function table and functions
1192           **
1193           **==============================================================================
1194           */
1195           
1196           void __MI_Instance_Ref(MI_Instance* self)
1197           {
1198               InstanceHeader* h = _HeaderOf((Instance*)self);
1199           
1200               if (h)
1201                   AtomicInc(&h->u.refs);
1202           }
1203           
1204           void __MI_Instance_Unref(MI_Instance* self)
1205           {
1206               InstanceHeader* h = _HeaderOf((Instance*)self);
1207           
1208 mike  1.1     if (h && AtomicDec(&h->u.refs))
1209                   __MI_Instance_Delete((MI_Instance*)self);
1210           }
1211           
1212           MI_Result MI_CALL __MI_Instance_Clone(
1213               const MI_Instance* self, 
1214               MI_Instance** inst)
1215           {
1216               return Instance_Clone(self, inst, NULL);
1217           }
1218           
1219           MI_Result MI_CALL __MI_Instance_Destruct(
1220               MI_Instance* self_)
1221           {
1222               Instance* self = _SelfOf(self_);
1223               Batch* batch;
1224               MI_Uint32 i;
1225           
1226               /* Check for null parameter */
1227               if (!self)
1228                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1229 mike  1.1 
1230               /* Save pointer to batch */
1231               batch = self->batch;
1232               if (!batch)
1233                   MI_RETURN(MI_RESULT_FAILED);
1234           
1235               /* Release serverName */
1236               if (self->serverName)
1237                   BFree(batch, self->serverName, CALLSITE);
1238           
1239               /* Release nameSpace */
1240               if (self->nameSpace)
1241                   BFree(batch, self->nameSpace, CALLSITE);
1242           
1243               /* Release all memory used by properties */
1244               for (i = 0; i < self->classDecl->numProperties; i++)
1245               {
1246                   const MI_PropertyDecl* pd = self->classDecl->properties[i];
1247                   Field* field = (Field*)((char*)self + pd->offset);
1248                   Field_Destruct(field, pd->type, batch);
1249               }
1250 mike  1.1 
1251               /* Free dynamic instance part (if any) */
1252               if ((void*)self != (void*)self_)
1253               {
1254                   for (i = 0; i < self->classDecl->numProperties; i++)
1255                   {
1256                       MI_PropertyDecl* pd = self->classDecl->properties[i];
1257                       BFree(batch, pd->name, CALLSITE);
1258                       BFree(batch, pd, CALLSITE);
1259                   }
1260           
1261                   BFree(batch, self->classDecl->name, CALLSITE);
1262                   BFree(batch, self->classDecl->properties, CALLSITE);
1263                   BFree(batch, self->classDecl, CALLSITE);
1264           
1265                   if ((void*)self != (void*)self_)
1266                       _FreeInstance(batch, self);
1267               }
1268           
1269               MI_RETURN(MI_RESULT_OK);
1270           }
1271 mike  1.1 
1272           MI_Result MI_CALL __MI_Instance_Delete(
1273               MI_Instance* self_)
1274           {
1275               Instance* self = _SelfOf(self_);
1276               MI_Result r;
1277               Batch* batch;
1278               MI_Boolean releaseBatch;
1279           
1280               /* Check for null parameter */
1281               if (!self)
1282                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1283           
1284               /* Save pointer to batch */
1285               batch = self->batch;
1286               if (!batch)
1287                   MI_RETURN(MI_RESULT_FAILED);
1288           
1289               /* Save */
1290               releaseBatch = self->releaseBatch;
1291           
1292 mike  1.1     /* Destruct */
1293               r = __MI_Instance_Destruct(self_);
1294               if (r != MI_RESULT_OK)
1295                   MI_RETURN(r);
1296           
1297               /* Release self pointer */
1298               _FreeInstance(batch, (Instance*)self_);
1299           
1300               /* Release the batch */
1301               if (releaseBatch)
1302                   Batch_Delete(batch);
1303           
1304               return r;
1305           }
1306           
1307           MI_Result MI_CALL __MI_Instance_IsA(
1308               const MI_Instance* self_,
1309               const MI_ClassDecl* classDecl,
1310               MI_Boolean* resultOut)
1311           {
1312               Instance* self = _SelfOf(self_);
1313 mike  1.1     const MI_ClassDecl* p;
1314           
1315               if (!self || !classDecl)
1316                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1317           
1318               for (p = self->classDecl; p; p = p->superClassDecl)
1319               {
1320                   if (p == classDecl)
1321                   {
1322                       if (resultOut)
1323                           *resultOut = MI_TRUE;
1324                       MI_RETURN(MI_RESULT_OK);
1325                   }
1326               }
1327           
1328               if (resultOut)
1329                   *resultOut = MI_FALSE;
1330           
1331               MI_RETURN(MI_RESULT_OK);
1332           }
1333           
1334 mike  1.1 MI_Result MI_CALL __MI_Instance_GetClassName(
1335               const MI_Instance* self_, 
1336               const MI_Char** classNameOut)
1337           {
1338               Instance* self = _SelfOf(self_);
1339           
1340               if (!self)
1341                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1342           
1343               if (classNameOut)
1344                   *classNameOut = self->classDecl->name;
1345           
1346               MI_RETURN(MI_RESULT_OK);
1347           }
1348           
1349           MI_Result MI_CALL __MI_Instance_SetNameSpace(
1350               MI_Instance* self_, 
1351               const MI_Char* nameSpace)
1352           {
1353               Instance* self = _SelfOf(self_);
1354               MI_Char* oldNameSpace;
1355 mike  1.1 
1356               /* Check parameters */
1357               if (!self)
1358                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1359           
1360               /* Save old namespace */
1361               oldNameSpace = self->nameSpace;
1362           
1363               /* Set new namespace */
1364               if (nameSpace)
1365               {
1366                   MI_Char* tmp = BStrdup(self->batch, nameSpace, CALLSITE);
1367           
1368                   if (!tmp)
1369                       MI_RETURN(MI_RESULT_FAILED);
1370           
1371                   self->nameSpace = tmp;
1372               }
1373               else
1374                   self->nameSpace = NULL;
1375           
1376 mike  1.1     /* Free old namespace */
1377               if (oldNameSpace)
1378                   BFree(self->batch, oldNameSpace, CALLSITE);
1379           
1380               MI_RETURN(MI_RESULT_OK);
1381           }
1382           
1383           MI_Result MI_CALL __MI_Instance_GetNameSpace(
1384               const MI_Instance* self_, 
1385               const MI_Char** nameSpaceOut)
1386           {
1387               Instance* self = _SelfOf(self_);
1388           
1389               if (!self)
1390                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1391           
1392               if (nameSpaceOut)
1393                   *nameSpaceOut = self->nameSpace;
1394           
1395               MI_RETURN(MI_RESULT_OK);
1396           }
1397 mike  1.1 
1398           MI_Result MI_CALL __MI_Instance_GetElementCount(
1399               const MI_Instance* self_,
1400               MI_Uint32* countOut)
1401           {
1402               Instance* self = _SelfOf(self_);
1403           
1404               if (!self)
1405                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1406           
1407               if (countOut)
1408                   *countOut = self->classDecl->numProperties;
1409           
1410               MI_RETURN(MI_RESULT_OK);
1411           }
1412           
1413           MI_Result MI_CALL __MI_Instance_AddElement(
1414               MI_Instance* self_,
1415               const MI_Char* name,
1416               const MI_Value* value,
1417               MI_Type type,
1418 mike  1.1     MI_Uint32 flags)
1419           {
1420               Instance* self = _SelfOf(self_);
1421               MI_Uint32 index;
1422               MI_ClassDecl* cd;
1423               MI_Uint32 tflags = 0;
1424           
1425               if (flags & MI_FLAG_BORROW)
1426                   tflags |= MI_FLAG_BORROW;
1427           
1428               if (flags & MI_FLAG_NULL)
1429                   tflags |= MI_FLAG_NULL;
1430           
1431               /* Check for null arguments */
1432               if (!self || !name)
1433                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1434           
1435               /* Reject attempts to extend a non-dynamic instances */
1436               if ((void*)self == (void*)self_)
1437                   MI_RETURN(MI_RESULT_FAILED);
1438           
1439 mike  1.1     /* Check that 'name' parameter is a legal CIM name */
1440               if (!LegalName(name))
1441                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1442           
1443               /* Find the property with this name */
1444               index = _FindPropertyDecl(self->classDecl, name);
1445           
1446               if (index != (MI_Uint32)-1)
1447                   MI_RETURN(MI_RESULT_ALREADY_EXISTS);
1448           
1449               /* Get pointer to class declaration */
1450               cd = (MI_ClassDecl*)self->classDecl;
1451           
1452               /* Extend size of instance and properties array as needed */
1453               if (cd->numProperties == _FindCapacity(cd->numProperties))
1454               {
1455                   MI_Uint32 cap;
1456                   MI_PropertyDecl** data;
1457           
1458                   /* Double old capacity */
1459                   cap = 2 * cd->numProperties;
1460 mike  1.1 
1461                   /* Reallocate properties array */
1462                   data = (MI_PropertyDecl**)BRealloc(
1463                       self->batch, 
1464                       cd->properties, 
1465                       cd->numProperties * sizeof(MI_PropertyDecl),
1466                       cap * sizeof(MI_PropertyDecl),
1467                       CALLSITE);
1468           
1469                   if (!data)
1470                       MI_RETURN(MI_RESULT_FAILED);
1471           
1472                   cd->properties = data;
1473            
1474                   /* Reallocate instance */
1475                   self = _ReallocInstance(
1476                       self->batch, 
1477                       self, 
1478                       sizeof(MI_Instance) + cd->numProperties * sizeof(Field),
1479                       sizeof(MI_Instance) + cap * sizeof(Field));
1480                   if (!self)
1481 mike  1.1             MI_RETURN(MI_RESULT_FAILED);
1482           
1483                   /* Set new self */
1484                   self->self = self;
1485               }
1486           
1487               /* Create and add new property */
1488               {
1489                   MI_PropertyDecl* pd;
1490           
1491                   /* Allocate new peroperty declaration */
1492                   pd = (MI_PropertyDecl*)BCalloc(
1493                       self->batch, sizeof(MI_PropertyDecl), CALLSITE);
1494           
1495                   if (!pd)
1496                       MI_RETURN(MI_RESULT_FAILED);
1497           
1498                   /* MI_PropertyDecl.flags */
1499                   pd->flags = flags;
1500           
1501                   /* MI_PropertyDecl.code */
1502 mike  1.1         pd->code = Hash(name);
1503           
1504                   /* MI_PropertyDecl.name */
1505                   pd->name = BStrdup(self->batch, name, CALLSITE);
1506           
1507                   if (!pd->name)
1508                       MI_RETURN(MI_RESULT_FAILED);
1509           
1510                   /* MI_PropertyDecl.type */
1511                   pd->type = type;
1512           
1513                   /* MI_PropertyDecl.offset */
1514                   pd->offset = sizeof(MI_Instance) + cd->numProperties*sizeof(Field);
1515           
1516                   /* Add property to array */
1517                   cd->properties[cd->numProperties++] = pd;
1518                   
1519                   /* Clear the new field */
1520                   memset((char*)self + pd->offset, 0, sizeof(Field));
1521           
1522                   /* Adjust size */
1523 mike  1.1         cd->size += sizeof(Field);
1524               }
1525           
1526               /* Reassign 'self' field (it may have changed) */
1527               ((Instance*)self_)->self = self;
1528           
1529               /* Copy self of self wrapper */
1530               memcpy(self_, self, sizeof(MI_Instance));
1531           
1532               /* Set the last property */
1533               MI_RETURN(__MI_Instance_SetElementAt(
1534                   self_, cd->numProperties - 1, value, type, tflags));
1535           }
1536           
1537           MI_Result MI_CALL __MI_Instance_SetElement(
1538               MI_Instance* self_, 
1539               const MI_Char* name, 
1540               const MI_Value* value,
1541               MI_Type type,
1542               MI_Uint32 flags)
1543           {
1544 mike  1.1     Instance* self = _SelfOf(self_);
1545               MI_Uint32 index;
1546           
1547               /* Check for null arguments */
1548               if (!self || !name)
1549                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1550           
1551               /* Find the property with this name */
1552               index = _FindPropertyDecl(self->classDecl, name);
1553           
1554               if (index == (MI_Uint32)-1)
1555                   MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
1556           
1557               MI_RETURN(__MI_Instance_SetElementAt(self_, index, value, type, flags));
1558           }
1559           
1560           MI_Result MI_CALL __MI_Instance_SetElementAt(
1561               MI_Instance* self_, 
1562               MI_Uint32 index,
1563               const MI_Value* value,
1564               MI_Type type,
1565 mike  1.1     MI_Uint32 flags)
1566           {
1567               Instance* self = _SelfOf(self_);
1568               const MI_PropertyDecl* pd;
1569               char* field;
1570           
1571               /* Check for null arguments */
1572               if (!self)
1573                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1574               
1575               /* Check whether index is in range */
1576               if (index > self->classDecl->numProperties)
1577                   MI_RETURN(MI_RESULT_FAILED);
1578           
1579               /* Get pointer to properties declaration */
1580               pd = self->classDecl->properties[index];
1581           
1582               /* Check the type */
1583               if (type != (MI_Type)pd->type)
1584                   MI_RETURN(MI_RESULT_TYPE_MISMATCH);
1585           
1586 mike  1.1     /* Get pointer to field */
1587               field = (char*)self + pd->offset;
1588           
1589               /* Set the value */
1590               {
1591                   MI_Result r = Field_Set(
1592                       (Field*)((char*)self + pd->offset),
1593                       pd->type,
1594                       value,
1595                       flags,
1596                       self->batch);
1597           
1598                   if (r != MI_RESULT_OK)
1599                       return r;
1600               }
1601           
1602               MI_RETURN(MI_RESULT_OK);
1603           }
1604           
1605           MI_Result MI_CALL __MI_Instance_GetElement(
1606               const MI_Instance* self_, 
1607 mike  1.1     const MI_Char* name, 
1608               MI_Value* valueOut,
1609               MI_Type* typeOut,
1610               MI_Uint32* flagsOut,
1611               MI_Uint32* indexOut)
1612           {
1613               Instance* self = _SelfOf(self_);
1614               MI_Uint32 index;
1615               MI_Result r;
1616           
1617               /* Check for null arguments */
1618               if (!self || !name)
1619                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1620           
1621               /* Find the property with this name */
1622               index = _FindPropertyDecl(self->classDecl, name);
1623           
1624               if (index == (MI_Uint32)-1)
1625                   MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
1626           
1627               r = __MI_Instance_GetElementAt(
1628 mike  1.1         self_, index, NULL, valueOut, typeOut, flagsOut);
1629           
1630               if (r != MI_RESULT_OK)
1631                   MI_RETURN(r);
1632           
1633               if (indexOut)
1634                   *indexOut = index;
1635           
1636               MI_RETURN(MI_RESULT_OK);
1637           }
1638           
1639           MI_Result MI_CALL __MI_Instance_GetElementAt(
1640               const MI_Instance* self_,
1641               MI_Uint32 index,
1642               const MI_Char** nameOut,
1643               MI_Value* valueOut,
1644               MI_Type* typeOut,
1645               MI_Uint32* flagsOut)
1646           {
1647               Instance* self = _SelfOf(self_);
1648               const MI_PropertyDecl* pd;
1649 mike  1.1     const Field* field;
1650           
1651               /* Check for null arguments */
1652               if (!self)
1653                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1654           
1655               /* Check for bounds error */
1656               if (index >= self->classDecl->numProperties)
1657                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1658           
1659               pd = self->classDecl->properties[index];
1660           
1661               /* Get pointer to field */
1662               field = (Field*)((char*)self + pd->offset);
1663           
1664               /* set nameOut */
1665               if (nameOut)
1666                   *nameOut = pd->name;
1667           
1668               /* set valueOut */
1669               if (valueOut)
1670 mike  1.1         memcpy(valueOut, field, Type_SizeOf((MI_Type)pd->type));
1671           
1672               /* Set existsOut */
1673               if (flagsOut)
1674               {
1675                   *flagsOut = pd->flags;
1676           
1677                   if (!Field_GetExists(field, (MI_Type)pd->type))
1678                       *flagsOut |= MI_FLAG_NULL;
1679               }
1680           
1681               /* Set typeOut */
1682               if (typeOut)
1683                   *typeOut = (MI_Type)pd->type;
1684           
1685               MI_RETURN(MI_RESULT_OK);
1686           }
1687           
1688           MI_Result MI_CALL __MI_Instance_ClearElement(
1689               MI_Instance* self_, 
1690               const MI_Char* name)
1691 mike  1.1 {
1692               Instance* self = _SelfOf(self_);
1693               MI_Uint32 index;
1694           
1695               /* Check for null arguments */
1696               if (!self || !name)
1697                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1698           
1699               /* Find the property with this name */
1700               index = _FindPropertyDecl(self->classDecl, name);
1701           
1702               if (index == (MI_Uint32)-1)
1703                   MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
1704           
1705               MI_RETURN(__MI_Instance_ClearElementAt(self_, index));
1706           }
1707           
1708           MI_Result MI_CALL __MI_Instance_ClearElementAt(
1709               MI_Instance* self_, 
1710               MI_Uint32 index)
1711           {
1712 mike  1.1     Instance* self = _SelfOf(self_);
1713               const MI_PropertyDecl* pd;
1714               char* field;
1715           
1716               /* Check for null arguments */
1717               if (!self)
1718                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1719               
1720               /* Check whether index is in range */
1721               if (index > self->classDecl->numProperties)
1722                   MI_RETURN(MI_RESULT_FAILED);
1723           
1724               /* Get pointer to properties declaration */
1725               pd = self->classDecl->properties[index];
1726           
1727               /* Get pointer to field */
1728               field = (char*)self + pd->offset;
1729           
1730               /* Clear the value */
1731               Field_Clear((Field*)((char*)self + pd->offset), pd->type, 
1732                   self->batch);
1733 mike  1.1 
1734               MI_RETURN(MI_RESULT_OK);
1735           }
1736           
1737           MI_Result MI_CALL Instance_Print(
1738               const MI_Instance* self_,
1739               FILE* os,
1740               MI_Uint32 level,
1741               MI_Boolean showNulls)
1742           {
1743               Instance* self = _SelfOf(self_);
1744               const MI_ClassDecl* cd = self->classDecl;
1745               MI_Uint32 i;
1746           
1747               /* Check for null arguments */
1748               if (!self)
1749                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1750               
1751               /* Print nameSpace and className */
1752               if (self->nameSpace)
1753               {
1754 mike  1.1         Indent(os, level);
1755                   Fzprintf(os, T("instance of %s:%s\n"), self->nameSpace, cd->name);
1756               }
1757               else
1758               {
1759                   Indent(os, level);
1760                   Fzprintf(os, T("instance of %s\n"), cd->name);
1761               }
1762           
1763               Indent(os, level);
1764               Fzprintf(os, T("{\n"));
1765               level++;
1766           
1767               /* Print the properties */
1768               for (i = 0; i < cd->numProperties; i++)
1769               {
1770                   const MI_PropertyDecl* pd = cd->properties[i];
1771                   const Field* field = (Field*)((char*)self + pd->offset);
1772           
1773                   if (showNulls || Field_GetExists(field, pd->type))
1774                   {
1775 mike  1.1             Indent(os, level);
1776           
1777                       if (pd->flags & MI_FLAG_KEY)
1778                           Fzprintf(os, T("[Key] "));
1779           
1780                       Fzprintf(os, T("%s="), pd->name);
1781           
1782                       Field_Print(field, os, pd->type, level);
1783           
1784                       if (pd->type == MI_INSTANCE || pd->type == MI_REFERENCE)
1785                       {
1786                           if (!field->instance.value)
1787                               fputc('\n', os);
1788                       }
1789                       else
1790                           fputc('\n', os);
1791                   }
1792               }
1793           
1794               level--;
1795               Indent(os, level);
1796 mike  1.1 
1797               Fzprintf(os, T("}\n"));
1798           
1799               MI_RETURN(MI_RESULT_OK);
1800           }
1801           
1802           MI_Result MI_CALL __MI_Instance_GetServerName(
1803               const MI_Instance* self,
1804               const MI_Char** name)
1805           {
1806               MI_RETURN(MI_RESULT_NOT_SUPPORTED);
1807           }
1808           
1809           MI_Result MI_CALL __MI_Instance_SetServerName(
1810               _Inout_ MI_Instance* self,
1811               _In_z_ const MI_Char* name)
1812           {
1813               MI_RETURN(MI_RESULT_NOT_SUPPORTED);
1814           }
1815           
1816           MI_Result MI_CALL __MI_Instance_GetClass(
1817 mike  1.1     _In_ const MI_Instance* self,
1818               _Outptr_ MI_Class** instanceClass)
1819           {
1820               MI_RETURN(MI_RESULT_NOT_SUPPORTED);
1821           }
1822           
1823           MI_Result MI_CALL __MI_Instance_Print(
1824               const MI_Instance* self,
1825               FILE* os,
1826               MI_Uint32 level)
1827           {
1828               return Instance_Print(self, os, level, MI_TRUE);
1829           }
1830           
1831           MI_InstanceFT __mi_instanceFT =
1832           {
1833               __MI_Instance_Clone,
1834               __MI_Instance_Destruct,
1835               __MI_Instance_Delete,
1836               __MI_Instance_IsA,
1837               __MI_Instance_GetClassName,
1838 mike  1.1     __MI_Instance_SetNameSpace,
1839               __MI_Instance_GetNameSpace,
1840               __MI_Instance_GetElementCount,
1841               __MI_Instance_AddElement,
1842               __MI_Instance_SetElement,
1843               __MI_Instance_SetElementAt,
1844               __MI_Instance_GetElement,
1845               __MI_Instance_GetElementAt,
1846               __MI_Instance_ClearElement,
1847               __MI_Instance_ClearElementAt,
1848               __MI_Instance_GetServerName,
1849               __MI_Instance_SetServerName,
1850               __MI_Instance_GetClass,
1851               __MI_Instance_Print,
1852           };

ViewCVS 0.9.2