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

ViewCVS 0.9.2