(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 krisbash 1.5 ** 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 mike     1.1 **
  14              ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15 krisbash 1.5 ** 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 mike     1.1 **
  19 krisbash 1.5 ** See the Apache 2 License for the specific language governing permissions
  20 mike     1.1 ** and limitations under the License.
  21              **
  22              **==============================================================================
  23              */
  24              
  25              #include <ctype.h>
  26              #include "instance.h"
  27              #include "helpers.h"
  28              #include "naming.h"
  29              #include "types.h"
  30              #include "schemadecl.h"
  31              #include "alloc.h"
  32              #include "field.h"
  33 krisbash 1.4 #include "class.h"
  34 krisbash 1.5 #include <pal/intsafe.h>
  35 krisbash 1.4 #include <stdio.h>
  36              #ifdef _MSC_VER
  37              #pragma prefast (disable: 28252)
  38              #pragma prefast (disable: 28253)
  39              #endif
  40              #include <wchar.h>
  41 mike     1.1 
  42              
  43              /*
  44              **==============================================================================
  45              **
  46              ** Local definitions
  47              **
  48              **==============================================================================
  49              */
  50              
  51              /* Magic number of InstanceHeader */
  52              static MI_Uint32 _MAGIC = 0xB26AEA60;
  53              
  54              /* Number of default pages for a self-owned batch object */
  55 krisbash 1.4 static MI_Uint32 _NUM_PAGES = INFINITE;
  56 mike     1.1 
  57              /* The minimum number of reserved properties for a dynamic instance */
  58 krisbash 1.5 static size_t _CAPACITY = 32;
  59 mike     1.1 
  60              /* Find capacity (lesser of _CAPACITY or x rounded to power of 2) */
  61 krisbash 1.5 static size_t _FindCapacity(size_t x)
  62 mike     1.1 {
  63                  if (x <= _CAPACITY)
  64                      return _CAPACITY;
  65                  else
  66                  {
  67 krisbash 1.5         size_t r = x - 1;
  68 mike     1.1 
  69                      r |= (r >> 1);
  70                      r |= (r >> 2);
  71                      r |= (r >> 4);
  72                      r |= (r >> 8);
  73                      r |= (r >> 16);
  74              
  75                      return r + 1;
  76                  }
  77              }
  78              
  79 krisbash 1.5 /*
  80 mike     1.1  * Obtains the self pointer for this instance. For static instances, this
  81               * it is the same as the instance parameter. For dynamic instances, the
  82               * self pointer is given by instance->self.
  83               */
  84              MI_INLINE Instance* _SelfOf(const MI_Instance* instance)
  85              {
  86                  Instance* self = (Instance*)instance;
  87              
  88                  if (self)
  89                  {
  90                      if (self->self)
  91                          self = self->self;
  92              
  93                      return self;
  94                  }
  95              
  96                  DEBUG_ASSERT(0);
  97                  return NULL;
  98              }
  99              
 100 krisbash 1.4 /* Return the index of the given property */
 101              MI_Uint32 _FindFeatureDecl(
 102                  MI_FeatureDecl** features,
 103                  MI_Uint32 numFeatures,
 104                  const MI_Char* name)
 105              {
 106                  MI_Uint32 code;
 107                  MI_FeatureDecl** start = features;
 108                  MI_FeatureDecl** p = start;
 109                  MI_FeatureDecl** end = start + numFeatures;
 110              
 111                  /* Zero-length CIM names are illegal */
 112                  if (*name == '\0')
 113                      return (MI_Uint32)-1;
 114              
 115                  code = Hash(name);
 116              
 117                  /* Find the property */
 118                  while (p != end)
 119                  {
 120                      if (p[0]->code == code && Tcscasecmp(p[0]->name, name) == 0)
 121 krisbash 1.4             return (MI_Uint32)(p - start);
 122                      p++;
 123                  }
 124              
 125                  /* Not found */
 126                  return (MI_Uint32)-1;
 127              }
 128              
 129              /* Return the index of the given property */
 130              MI_INLINE MI_Uint32 _FindPropertyDeclIndex(
 131                  const MI_ClassDecl* cd,
 132                  const MI_Char* name)
 133              {
 134                  return _FindFeatureDecl(
 135                      (MI_FeatureDecl**)cd->properties,
 136                      cd->numProperties,
 137                      name);
 138              }
 139              
 140 mike     1.1 /* Return the index of the given property or (MI_Uin32)-1 if not found */
 141              static MI_Uint32 _FindPropertyDecl(
 142                  const MI_ClassDecl* cd,
 143 krisbash 1.4     const ZChar* name)
 144 mike     1.1 {
 145                  MI_PropertyDecl** start = cd->properties;
 146                  MI_PropertyDecl** end = start + cd->numProperties;
 147                  MI_PropertyDecl** p = start;
 148                  MI_Uint32 code;
 149              
 150                  code = Hash(name);
 151              
 152 krisbash 1.5     while (p != end)
 153 mike     1.1     {
 154 krisbash 1.4         if ((*p)->code == code && Tcscasecmp((*p)->name, name) == 0)
 155 mike     1.1             return (MI_Uint32)(p - start);
 156                      p++;
 157                  }
 158              
 159                  return (MI_Uint32)-1;
 160              }
 161              
 162 krisbash 1.4 
 163 mike     1.2 static MI_PropertyDecl* _LookupPropertyDecl(
 164                  const MI_ClassDecl* cd,
 165 krisbash 1.4     const ZChar* name)
 166 mike     1.2 {
 167                  MI_Uint32 index = _FindPropertyDecl(cd, name);
 168              
 169                  if (index == (MI_Uint32)-1)
 170                      return NULL;
 171              
 172                  return cd->properties[index];
 173              }
 174 krisbash 1.4 static MI_Qualifier * _CloneQualifierDecl(
 175                  MI_Qualifier * qualifier,
 176                  _Inout_ Batch *batch)
 177              {
 178                  MI_Qualifier *newQualifier = Batch_Get(batch, sizeof(MI_Qualifier));
 179                  if (newQualifier == NULL)
 180                  {
 181 krisbash 1.5         return NULL;
 182 krisbash 1.4     }
 183                  memset(newQualifier, 0, sizeof(*newQualifier));
 184                  newQualifier->name = Batch_Tcsdup(batch, qualifier->name);
 185                  if (newQualifier->name == NULL)
 186                  {
 187 krisbash 1.5         return NULL;
 188 krisbash 1.4     }
 189                  newQualifier->type = qualifier->type;
 190                  newQualifier->flavor = qualifier->flavor;
 191                  /* Clone only boolean values. */
 192                  if (qualifier->value && qualifier->type == MI_BOOLEAN)
 193                  {
 194                      newQualifier->value = Batch_Get(batch, sizeof(MI_Boolean));
 195                      if (newQualifier->value == NULL)
 196                      {
 197                          return NULL;
 198                      }
 199                      *(MI_Boolean*)newQualifier->value = *(MI_Boolean*)qualifier->value;
 200                  }
 201                  else
 202                  {
 203                      newQualifier->value = NULL;
 204                  }
 205              
 206                  return newQualifier;
 207              }
 208              
 209 krisbash 1.4 static MI_Qualifier  **_CloneQualifierDecls(
 210                  MI_Qualifier **qualifiers,
 211                  MI_Uint32 numQualifiers,
 212                  _Inout_ Batch *batch)
 213              {
 214                  MI_Qualifier **newQualifiers = Batch_Get(batch, sizeof(MI_Qualifier*)*numQualifiers);
 215                  MI_Uint32 qualifierIndex = 0;
 216                  if (newQualifiers == NULL)
 217                  {
 218 krisbash 1.5         return NULL;
 219 krisbash 1.4     }
 220                  for (;qualifierIndex != numQualifiers; qualifierIndex++)
 221                  {
 222                      newQualifiers[qualifierIndex] = _CloneQualifierDecl(qualifiers[qualifierIndex], batch);
 223                      if (newQualifiers[qualifierIndex] == NULL)
 224                      {
 225 krisbash 1.5             return NULL;
 226 krisbash 1.4         }
 227                  }
 228              
 229                  return newQualifiers;
 230              }
 231 mike     1.2 
 232 mike     1.1 static MI_PropertyDecl* _ClonePropertyDecl(
 233                  const MI_PropertyDecl* pd,
 234                  Batch* batch)
 235              {
 236                  MI_PropertyDecl* p;
 237              
 238                  p = (MI_PropertyDecl*)BCalloc(batch, sizeof(MI_PropertyDecl), CALLSITE);
 239              
 240                  if (!p)
 241                      return NULL;
 242              
 243                  if (pd->name)
 244                  {
 245                      p->name = BStrdup(batch, pd->name, CALLSITE);
 246 krisbash 1.4 
 247 mike     1.1         if (!p->name)
 248                          return NULL;
 249                  }
 250              
 251 krisbash 1.4     p->code = pd->code;
 252 mike     1.1     p->flags = pd->flags;
 253                  p->type = pd->type;
 254                  p->offset = pd->offset;
 255              
 256 krisbash 1.4     if (pd->qualifiers && pd->numQualifiers)
 257                  {
 258                      p->qualifiers = _CloneQualifierDecls(pd->qualifiers, pd->numQualifiers, batch);
 259                      if (p->qualifiers == NULL)
 260                      {
 261                          return NULL;  /* Returning NULL causes whole batch to destruct */
 262                      }
 263                      p->numQualifiers = pd->numQualifiers;
 264 krisbash 1.5     }
 265 krisbash 1.4 
 266 mike     1.1     return p;
 267              }
 268              
 269              static MI_PropertyDecl** _ClonePropertyDecls(
 270                  MI_PropertyDecl** properties,
 271 krisbash 1.5     size_t size,
 272 mike     1.1     Batch* batch)
 273              {
 274                  MI_PropertyDecl** data;
 275                  MI_Uint32 i;
 276              
 277                  /* Allocate at least _CAPACITY properties */
 278 krisbash 1.5     size_t cap = (size < _CAPACITY) ? _CAPACITY : size;
 279 mike     1.1 
 280                  /* Allocate properties array */
 281                  data = (MI_PropertyDecl**)BAlloc(batch, sizeof(MI_PropertyDecl*) * cap,
 282                      CALLSITE);
 283                  if (!data)
 284                      return NULL;
 285              
 286                  /* Copy each property */
 287                  for (i = 0; i < size; i++)
 288                  {
 289                      MI_PropertyDecl* pd = _ClonePropertyDecl(properties[i], batch);
 290                      if (!pd)
 291                          return NULL;
 292              
 293                      data[i] = pd;
 294                  }
 295              
 296                  return data;
 297              }
 298              
 299 krisbash 1.4 MI_ClassDecl* _CloneClassDecl(
 300 mike     1.1     const MI_ClassDecl* cd,
 301                  Batch* batch)
 302              {
 303                  MI_ClassDecl* p;
 304              
 305                  /* Instance.classDecl */
 306                  p = (MI_ClassDecl*)BCalloc(batch, sizeof(MI_ClassDecl), CALLSITE);
 307                  if (!p)
 308                      return NULL;
 309              
 310                  /* Instance.name */
 311                  if (cd->name)
 312                  {
 313                      p->name = BStrdup(batch, cd->name, CALLSITE);
 314 krisbash 1.4 
 315 mike     1.1         if (!p->name)
 316                          return NULL;
 317                  }
 318              
 319 krisbash 1.4     /* Instance.code */
 320                  p->code = cd->code;
 321              
 322 mike     1.1     /* Instance.size */
 323                  p->size = cd->size;
 324              
 325                  /* Instance.properties */
 326                  {
 327 krisbash 1.5         p->properties = _ClonePropertyDecls(cd->properties, cd->numProperties,
 328 mike     1.1             batch);
 329              
 330                      if (!p->properties)
 331                          return NULL;
 332              
 333                      p->numProperties = cd->numProperties;
 334 krisbash 1.5     }
 335                  p->owningClass = (MI_Class*)-1; //We are using this clone because it is a dynamic classDecl, so mark this classDecl as dynamic
 336 mike     1.1     return p;
 337              }
 338              
 339              MI_INLINE InstanceHeader* _HeaderOf(Instance* self)
 340              {
 341                  return self ? ((InstanceHeader*)self - 1) : NULL;
 342              }
 343              
 344              MI_INLINE Instance* _InstanceOf(InstanceHeader* self)
 345              {
 346                  return self ? (Instance*)(self + 1) : NULL;
 347              }
 348              
 349              static Instance* _AllocInstance(Batch* batch, size_t size)
 350              {
 351                  InstanceHeader* h = (InstanceHeader*)BCalloc(
 352 krisbash 1.5         batch,
 353                      sizeof(InstanceHeader) + size,
 354 mike     1.1         CALLSITE);
 355              
 356                  if (!h)
 357                      return NULL;
 358              
 359                  h->magic = _MAGIC;
 360                  h->u.refs = 1;
 361                  return _InstanceOf(h);
 362              }
 363              
 364              static Instance* _ReallocInstance(
 365 krisbash 1.5     Batch* batch,
 366                  Instance* self,
 367                  size_t oldSize,
 368 mike     1.1     size_t newSize)
 369              {
 370                  InstanceHeader* h = (InstanceHeader*)BRealloc(
 371 krisbash 1.5         batch,
 372                      _HeaderOf(self),
 373 mike     1.1         sizeof(InstanceHeader) + oldSize,
 374                      sizeof(InstanceHeader) + newSize,
 375                      CALLSITE);
 376              
 377                  if (!h)
 378                      return NULL;
 379              
 380                  h->magic = _MAGIC;
 381                  h->u.refs = 1;
 382              
 383                  return _InstanceOf(h);
 384              }
 385              
 386              static void _FreeInstance(
 387 krisbash 1.5     Batch* batch,
 388 mike     1.1     Instance* self)
 389              {
 390                  InstanceHeader* h = _HeaderOf(self);
 391              
 392                  if (h)
 393                  {
 394                      DEBUG_ASSERT(h->magic == _MAGIC);
 395              #if defined(CONFIG_ENABLE_DEBUG)
 396                      memset(h, 0xDD, sizeof(InstanceHeader) + sizeof(Instance));
 397              #endif
 398                      BFree(batch, h, CALLSITE);
 399                  }
 400              }
 401              
 402              /*
 403               * Each dynamic instance is 'wrapped' inside another instance (referred to
 404 krisbash 1.5  * by the self field). This requiredment is imposed by the
 405 mike     1.1  * MI_Instance_AddElement() function, which does not allow the address of
 406               * the instance to change. Hence, indirection is required to allow the inner
 407 krisbash 1.5  * instance to be relocated in memory as new properties are added. The
 408 mike     1.1  * resulting layout is depicted below.
 409 krisbash 1.5  *
 410 mike     1.1  *        (Wrapper)
 411               *     +-------------+
 412               *     | MI_Instance |
 413               *     +---------+---+
 414               *     |         |   |         (Inner)
 415               *     +---------+---+     +-------------+
 416               *     | self    | ------> | MI_Instance |
 417               *     +---------+---+     +---------+---+
 418               *                         |         |   |
 419               *                         +---------+---+
 420               *                         |         |   |
 421               *                         +---------+---+
 422               *
 423               * All methods of the instance type, must resolve the self pointer using
 424 krisbash 1.5  * _SelfOf(), which either returns the sole parameter itself (for static
 425 mike     1.1  * instances) or the self field (for dynamic instances).
 426               *
 427               */
 428              static Instance* _WrapInstance(
 429 krisbash 1.5     Instance* self,
 430 mike     1.1     Batch* batch)
 431              {
 432                  Instance* wrapper;
 433              
 434                  if (!self)
 435                      return NULL;
 436              
 437                  /* Allocate space for outer wrapper instance */
 438                  wrapper = (Instance*)_AllocInstance(batch, sizeof(MI_Instance));
 439                  if (!wrapper)
 440                      return NULL;
 441              
 442                  /* Copy fields from inner instance to outer instance */
 443                  *wrapper = *self;
 444              
 445                  /* Set outer instance self to point to inner instance */
 446                  wrapper->self = self;
 447              
 448                  return wrapper;
 449              }
 450              
 451 mike     1.1 MI_Uint32 _CountKeys(
 452                  const Instance* self)
 453              {
 454                  MI_Uint32 n = 0;
 455                  const MI_ClassDecl* cd = self->classDecl;
 456                  MI_Uint32 i;
 457              
 458                  for (i = 0; i < cd->numProperties; i++)
 459                  {
 460                      if (cd->properties[i]->flags & MI_FLAG_KEY)
 461                          n++;
 462                  }
 463              
 464                  return n;
 465              }
 466              
 467              /*
 468              **==============================================================================
 469              **
 470              ** Public definitions
 471              **
 472 mike     1.1 **==============================================================================
 473              */
 474              
 475              MI_Result MI_CALL Instance_Construct(
 476                  MI_Instance* self_,
 477                  const MI_ClassDecl* classDecl,
 478                  Batch* batch_)
 479              {
 480                  Instance* self = (Instance*)self_;
 481                  MI_ClassDecl* cd = (MI_ClassDecl*)classDecl;
 482                  Batch* batch = batch_;
 483              
 484                  /* Check for null arguments */
 485                  if (!self || !cd)
 486                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 487              
 488                  /* Create a new batch */
 489                  if (!batch)
 490                  {
 491                      batch = Batch_New(_NUM_PAGES);
 492                      if (!batch)
 493 mike     1.1             return MI_RESULT_FAILED;
 494                  }
 495              
 496                  /* Zero-fill the object */
 497                  memset(self, 0, cd->size);
 498              
 499                  /* MI_Instance.ft */
 500                  self->ft = &__mi_instanceFT;
 501              
 502                  /* MI_Instance.self */
 503                  self->self = self;
 504              
 505 krisbash 1.4      /* MI_Instance.classDecl */
 506                  if ((cd->flags & (MI_FLAG_CLASS|MI_FLAG_ASSOCIATION|MI_FLAG_INDICATION)) && (cd->owningClass == NULL))
 507                  {
 508                      //Should be static
 509                      self->classDecl = cd;
 510                  }
 511                  else if ((cd->flags & (MI_FLAG_CLASS|MI_FLAG_ASSOCIATION|MI_FLAG_INDICATION)) && (cd->owningClass != (MI_Class*)-1))
 512                  {
 513                      //Bump up the ref-count on the owning classDecl if it is a class AND it is not a static classDecl
 514                      MI_Class *newClass;
 515                      MI_Result result = MI_Class_Clone(cd->owningClass, &newClass);
 516                      if (result != MI_RESULT_OK)
 517                          return result;
 518              
 519                      self->classDecl = newClass->classDecl;
 520                  }
 521                  else if (cd->flags & (MI_FLAG_CLASS|MI_FLAG_ASSOCIATION|MI_FLAG_INDICATION))
 522                  {
 523                      if (!batch)
 524                      {
 525                          assert(0);
 526 krisbash 1.4             MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 527                      }
 528              
 529                      //This is a class, so do a full clone
 530                      self->classDecl = Class_Clone_ClassDecl(batch, cd);
 531                      if (self->classDecl == NULL)
 532                          return MI_RESULT_FAILED;
 533                  }
 534                  else
 535                  {
 536                      if (!batch)
 537                      {
 538                          assert(0);
 539                          MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 540                      }
 541              
 542                      //This may be a parameter, so need to do a reduced clone
 543                      self->classDecl = _CloneClassDecl(cd, batch);
 544                      if (self->classDecl == NULL)
 545                          return MI_RESULT_FAILED;
 546                  }
 547 mike     1.1 
 548                  /* MI_Instance.batch */
 549                  self->batch = batch;
 550              
 551                  /* Flags */
 552                  self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
 553              
 554                  MI_RETURN(MI_RESULT_OK);
 555              }
 556              
 557 krisbash 1.4 _Use_decl_annotations_
 558 mike     1.1 MI_Result Instance_New(
 559                  MI_Instance** selfOut,
 560                  const MI_ClassDecl* classDecl,
 561                  Batch* batch_)
 562              {
 563                  Instance* self;
 564                  Batch* batch = batch_;
 565                  MI_Result r;
 566              
 567                  /* Check for null arguments */
 568 krisbash 1.4     if (!selfOut || !classDecl)
 569 mike     1.1         MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 570              
 571                  /* Null out selfOut */
 572                  *selfOut = NULL;
 573              
 574                  /* Create a new batch */
 575                  if (!batch)
 576                  {
 577                      batch = Batch_New(_NUM_PAGES);
 578                      if (!batch)
 579                          return MI_RESULT_FAILED;
 580                  }
 581              
 582                  /* Allocate structure */
 583                  self = _AllocInstance(batch, classDecl->size);
 584                  if (!self)
 585                  {
 586                      r = MI_RESULT_FAILED;
 587                      goto failed;
 588                  }
 589              
 590 mike     1.1     /* Initialize the object */
 591                  r = Instance_Construct((MI_Instance*)self, classDecl, batch);
 592                  if (r != MI_RESULT_OK)
 593                      goto failed;
 594              
 595                  /* Arrange to release batch if we created it */
 596                  self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
 597              
 598                  *selfOut = (MI_Instance*)self;
 599                  MI_RETURN(MI_RESULT_OK);
 600              
 601              failed:
 602                  if (batch != batch_)
 603                      Batch_Delete(batch);
 604                  return r;
 605              }
 606              
 607 krisbash 1.4 _Use_decl_annotations_
 608 mike     1.1 MI_Result MI_CALL Instance_InitConvert(
 609                  MI_Instance* self_,
 610                  const MI_ClassDecl* cd1,
 611                  const MI_Instance* inst_,
 612                  MI_Boolean keysOnly,
 613                  MI_Boolean allowKeylessInst,
 614                  MI_Boolean copy,
 615 krisbash 1.4     Batch* batch_,
 616                  MI_Uint32 flags)
 617 mike     1.1 {
 618                  Instance* self;
 619                  const Instance* inst = _SelfOf(inst_);
 620                  MI_Uint32 i;
 621                  MI_Result r;
 622                  const MI_ClassDecl* cd2;
 623                  const MI_SchemaDecl* sd1;
 624                  Batch* batch = batch_;
 625              
 626 krisbash 1.4     /* Check parameters */
 627                  if (!self_ || !cd1 || !inst)
 628                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
 629              
 630                  /* Create a new batch */
 631                  if (!batch)
 632                  {
 633                      batch = Batch_New(_NUM_PAGES);
 634                      if (!batch)
 635                          return MI_RESULT_SERVER_LIMITS_EXCEEDED;
 636                  }
 637              
 638 mike     1.1     /* Resolve the schema declaration (based on type) */
 639                  if (cd1->flags & MI_FLAG_METHOD)
 640                      sd1 = ((MI_MethodDecl*)cd1)->schema;
 641                  else if (cd1->flags & MI_FLAG_CLASS)
 642                      sd1 = cd1->schema;
 643                  else
 644 mike     1.2     {
 645 mike     1.1         return MI_RESULT_FAILED;
 646 mike     1.2     }
 647 mike     1.1 
 648                  cd2 = inst->classDecl;
 649              
 650                  /* Initialize the instance */
 651                  r = Instance_Construct(self_, cd1, batch);
 652                  if (r != MI_RESULT_OK)
 653 mike     1.2     {
 654 mike     1.1         goto failed;
 655 mike     1.2     }
 656 mike     1.1 
 657                  /* Get the self pointer from the newly initialized instance */
 658                  self = _SelfOf(self_);
 659              
 660                  /* Arrange to release the batch */
 661                  self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
 662              
 663                  /* Copy the nameSpace */
 664                  if (inst->nameSpace)
 665                  {
 666                      self->nameSpace = BStrdup(batch, inst->nameSpace, CALLSITE);
 667                      if (!self->nameSpace)
 668                      {
 669 krisbash 1.4             r = MI_RESULT_SERVER_LIMITS_EXCEEDED;
 670 mike     1.1             goto failed;
 671                      }
 672                  }
 673              
 674                  /* Copy the serverName */
 675                  if (inst->serverName)
 676                  {
 677                      self->serverName = BStrdup(batch, inst->serverName, CALLSITE);
 678                      if (!self->serverName)
 679                      {
 680 krisbash 1.4             r = MI_RESULT_SERVER_LIMITS_EXCEEDED;
 681 mike     1.1             goto failed;
 682                      }
 683                  }
 684              
 685                  /* Validate that the two instances share the same key structure */
 686                  if (!allowKeylessInst)
 687                  {
 688                      for (i = 0; i < cd1->numProperties; i++)
 689                      {
 690                          const MI_PropertyDecl* pd1 = cd1->properties[i];
 691              
 692                          if (pd1->flags & MI_FLAG_KEY)
 693                          {
 694                              MI_Uint32 index;
 695              
 696                              index = _FindPropertyDecl(cd2, pd1->name);
 697                              if (index == (MI_Uint32)-1)
 698                              {
 699 krisbash 1.4                     if (pd1->value)
 700                                  {
 701                                      //add default key value
 702                                      MI_Value* value = (MI_Value*)pd1->value;
 703                                      r = MI_Instance_SetElementAt(self_, i, value, pd1->type, MI_FLAG_BORROW);
 704                                      if (r != MI_RESULT_OK)
 705                                      {
 706                                          goto failed;
 707                                      }
 708              
 709                                  }
 710                                  else
 711                                  {
 712                                      r = MI_RESULT_NO_SUCH_PROPERTY;
 713                                      goto failed;
 714                                  }
 715 mike     1.1                 }
 716                          }
 717                      }
 718              
 719                      for (i = 0; i < cd2->numProperties; i++)
 720                      {
 721                          const MI_PropertyDecl* pd2 = cd2->properties[i];
 722              
 723                          if (pd2->flags & MI_FLAG_KEY)
 724                          {
 725                              MI_Uint32 index;
 726              
 727                              index = _FindPropertyDecl(cd1, pd2->name);
 728                              if (index == (MI_Uint32)-1)
 729                              {
 730 krisbash 1.4                     r = MI_RESULT_NO_SUCH_PROPERTY;
 731 mike     1.1                     goto failed;
 732                              }
 733                          }
 734                      }
 735                  }
 736              
 737                  /* ATTN: ignore unknown properties? */
 738              
 739                  /* Set non-null properties */
 740                  for (i = 0; i < cd2->numProperties; i++)
 741                  {
 742                      const MI_PropertyDecl* pd2 = cd2->properties[i];
 743                      Field* field = (Field*)((char*)inst + pd2->offset);
 744              
 745                      /* If requested, ignore non-keys */
 746                      if (keysOnly && !(pd2->flags & MI_FLAG_KEY))
 747                          continue;
 748              
 749                      /* Set the non-null key values */
 750                      if (Field_GetExists(field, pd2->type))
 751                      {
 752 mike     1.1             if (pd2->type == MI_STRING)
 753                          {
 754                              r = Instance_SetElementFromString(self_, pd2->name,
 755 krisbash 1.4                     ((MI_Value*)field)->string, flags);
 756 mike     1.1 
 757                              if (r != MI_RESULT_OK)
 758                              {
 759                                  goto failed;
 760                              }
 761                          }
 762                          else if (pd2->type == MI_STRINGA)
 763                          {
 764                              r = Instance_SetElementFromStringA(self_, pd2->name,
 765 krisbash 1.4                     (const ZChar**)((MI_Value*)field)->stringa.data,
 766                                  ((MI_Value*)field)->stringa.size,
 767                                  flags);
 768 mike     1.1 
 769                              if (r != MI_RESULT_OK)
 770                              {
 771                                  goto failed;
 772                              }
 773                          }
 774                          else if (pd2->type == MI_INSTANCE || pd2->type == MI_REFERENCE)
 775                          {
 776                              MI_Instance* tmpInst;
 777                              MI_ClassDecl* tmpCd;
 778 mike     1.2                 MI_Type type;
 779 krisbash 1.4                 MI_Boolean allowKeylessEmbedInst = (pd2->type == MI_INSTANCE) ? MI_TRUE : MI_FALSE;
 780 mike     1.1 
 781                              /* Find the class declaration in the schema */
 782 krisbash 1.5                 tmpCd = SchemaDecl_FindClassDecl(sd1,
 783 mike     1.1                     _SelfOf(((MI_Value*)field)->instance)->classDecl->name);
 784              
 785                              if (!tmpCd)
 786                              {
 787 krisbash 1.4                     r = MI_RESULT_NO_SUCH_PROPERTY;
 788 mike     1.1                     goto failed;
 789                              }
 790              
 791                              /* Allocate static instance of this class */
 792 krisbash 1.4                 r = Instance_New(&tmpInst, tmpCd, batch);
 793                              if (r != MI_RESULT_OK)
 794 mike     1.1                 {
 795                                  goto failed;
 796                              }
 797              
 798                              /* Convert instance */
 799                              r = Instance_InitConvert(tmpInst, tmpCd,
 800 krisbash 1.5                     ((MI_Value*)field)->instance, keysOnly, allowKeylessEmbedInst, copy,
 801 krisbash 1.4                     ((Instance*)tmpInst)->batch, flags);
 802 mike     1.1 
 803                              if (r != MI_RESULT_OK)
 804                              {
 805                                  __MI_Instance_Delete(tmpInst);
 806                                  goto failed;
 807                              }
 808              
 809 mike     1.2                 /* Get the target property type */
 810 mike     1.1                 {
 811 mike     1.2                     MI_PropertyDecl* pd = _LookupPropertyDecl(cd1, pd2->name);
 812 mike     1.1 
 813 mike     1.2                     if (!pd)
 814 mike     1.1                     {
 815 mike     1.2                         r = MI_RESULT_NO_SUCH_PROPERTY;
 816 mike     1.1                         goto failed;
 817                                  }
 818              
 819 mike     1.2                     type = pd->type;
 820                              }
 821              
 822                              /* Reject if not instance or reference */
 823 mike     1.1 
 824 mike     1.2                 switch (type)
 825                              {
 826                                  case MI_INSTANCE:
 827                                  case MI_REFERENCE:
 828                                  {
 829                                      MI_Value v;
 830                                      v.instance = tmpInst;
 831 mike     1.1 
 832 mike     1.2                         r = __MI_Instance_SetElement(
 833 krisbash 1.5                             self_,
 834                                          pd2->name,
 835                                          &v,
 836 mike     1.2                             type,
 837                                          MI_FLAG_ADOPT);
 838              
 839                                      break;
 840                                  }
 841                                  case MI_INSTANCEA:
 842                                  case MI_REFERENCEA:
 843                                  {
 844                                      MI_Value v;
 845                                      v.instancea.size = 1;
 846 krisbash 1.5                         v.instancea.data =
 847 mike     1.2                             BAlloc(batch, sizeof(void*), CALLSITE);
 848              
 849                                      if (!v.instancea.data)
 850                                      {
 851                                          __MI_Instance_Delete(tmpInst);
 852                                          r = MI_RESULT_FAILED;
 853                                          goto failed;
 854                                      }
 855              
 856                                      v.instancea.data[0] = tmpInst;
 857              
 858                                      r = __MI_Instance_SetElement(
 859 krisbash 1.5                             self_,
 860                                          pd2->name,
 861                                          &v,
 862 mike     1.2                             type,
 863                                          MI_FLAG_ADOPT);
 864              
 865                                      break;
 866                                  }
 867                                  default:
 868                                  {
 869                                      r = MI_RESULT_TYPE_MISMATCH;
 870                                      break;
 871                                  }
 872 mike     1.1                 }
 873              
 874                              if (r != MI_RESULT_OK)
 875                              {
 876                                  __MI_Instance_Delete(tmpInst);
 877                                  r = MI_RESULT_TYPE_MISMATCH;
 878                                  goto failed;
 879                              }
 880                          }
 881                          else if (pd2->type == MI_INSTANCEA || pd2->type == MI_REFERENCEA)
 882                          {
 883                              MI_Value v;
 884                              MI_Uint32 j;
 885 krisbash 1.4                 MI_Boolean allowKeylessEmbedInst = (pd2->type == MI_INSTANCEA) ? MI_TRUE : MI_FALSE;
 886 mike     1.1 
 887                              v.instancea.size = ((MI_Value*)field)->instancea.size;
 888 krisbash 1.5                 v.instancea.data = BAlloc(batch,
 889 mike     1.1                     v.instancea.size * sizeof(void*), CALLSITE);
 890              
 891                              if (!v.instancea.data)
 892                              {
 893 krisbash 1.4                     r = MI_RESULT_SERVER_LIMITS_EXCEEDED;
 894 mike     1.1                     goto failed;
 895                              }
 896 krisbash 1.5 
 897 mike     1.1                 for (j = 0; j < v.instancea.size; j++)
 898                              {
 899                                  MI_Instance* tmpInst;
 900                                  MI_ClassDecl* tmpCd;
 901              
 902                                  /* Find the schema declaration */
 903                                  tmpCd = SchemaDecl_FindClassDecl(sd1, _SelfOf(((
 904                                      MI_Value*)field)->instancea.data[j])->classDecl->name);
 905              
 906                                  if (!tmpCd)
 907                                  {
 908 krisbash 1.4                         r = MI_RESULT_NO_SUCH_PROPERTY;
 909 mike     1.1                         goto failed;
 910                                  }
 911              
 912                                  /* Allocate the instance for the provider */
 913 krisbash 1.4                     r = Instance_New(&tmpInst,tmpCd,batch);
 914                                  if (r != MI_RESULT_OK)
 915 mike     1.1                     {
 916                                      goto failed;
 917                                  }
 918              
 919                                  r = Instance_InitConvert(tmpInst, tmpCd,
 920 krisbash 1.5                         ((MI_Value*)field)->instancea.data[j], keysOnly, allowKeylessEmbedInst, copy,
 921 krisbash 1.4                         ((Instance*)tmpInst)->batch, flags);
 922 mike     1.1 
 923                                  if (r != MI_RESULT_OK)
 924                                  {
 925                                      MI_Uint32 k;
 926              
 927                                      for (k = 0; k < j; k++)
 928                                          __MI_Instance_Delete(v.instancea.data[k]);
 929              
 930                                      goto failed;
 931                                  }
 932              
 933                                  v.instancea.data[j] = tmpInst;
 934                              }
 935              
 936                              /* Set the value */
 937                              r = __MI_Instance_SetElement(self_, pd2->name, &v, pd2->type,
 938                                  MI_FLAG_ADOPT);
 939              
 940 krisbash 1.4                 /* Allow conversion from reference array to instance array */
 941                              if (r == MI_RESULT_TYPE_MISMATCH && pd2->type == MI_INSTANCEA)
 942                              {
 943                                  r = __MI_Instance_SetElement(self_, pd2->name, &v,
 944                                      MI_REFERENCEA, MI_FLAG_ADOPT);
 945                              }
 946              
 947 mike     1.1                 if (r != MI_RESULT_OK)
 948                              {
 949                                  for (j = 0; j < v.instancea.size; j++)
 950                                      __MI_Instance_Delete(v.instancea.data[j]);
 951              
 952                                  goto failed;
 953                              }
 954                          }
 955                          else
 956                          {
 957                              MI_Uint32 tmpFlags = copy ? 0 : MI_FLAG_BORROW;
 958              
 959                              /* Set the value */
 960                              r = __MI_Instance_SetElement(self_, pd2->name, (MI_Value*)field,
 961                                  pd2->type, tmpFlags);
 962              
 963                              if (r != MI_RESULT_OK)
 964                              {
 965                                  goto failed;
 966                              }
 967                          }
 968 mike     1.1         }
 969                  }
 970              
 971              failed:
 972                  if (batch != batch_)
 973                      Batch_Delete(batch);
 974                  return r;
 975              }
 976              
 977              MI_Result MI_CALL Instance_Clone(
 978 krisbash 1.5     const MI_Instance* self_,
 979 mike     1.1     MI_Instance** instOut,
 980                  Batch* batch_)
 981              {
 982 krisbash 1.4     const Instance* self;
 983 mike     1.1     Batch* batch = batch_;
 984                  Instance* inst;
 985                  MI_Uint32 i;
 986                  MI_Result r;
 987              
 988 krisbash 1.4     /* Check for externally defined instance */
 989                  if (self_ && self_->ft != &__mi_instanceFT && self_->ft != NULL)
 990                      return MI_Instance_Clone(self_, instOut);
 991              
 992                  self = _SelfOf(self_);
 993              
 994 mike     1.1     /* Check for a null parameter */
 995                  if (!self || !instOut)
 996                  {
 997                      r = MI_RESULT_FAILED;
 998                      goto failed;
 999                  }
1000              
1001                  /* Create new batch? */
1002                  if (!batch)
1003                  {
1004                      batch = Batch_New(_NUM_PAGES);
1005                      if (!batch)
1006                          return MI_RESULT_FAILED;
1007                  }
1008              
1009                  /* Allocate the new instance */
1010                  {
1011                      MI_Uint32 cap = sizeof(MI_Instance) + _CAPACITY * sizeof(Field);
1012              
1013                      if (self->classDecl->size > cap)
1014                          cap = self->classDecl->size;
1015 mike     1.1 
1016                      inst = _AllocInstance(batch, cap);
1017                      if (!inst)
1018                      {
1019                          r = MI_RESULT_FAILED;
1020                          goto failed;
1021                      }
1022                  }
1023              
1024                  /* Instance.self */
1025                  inst->self = inst;
1026              
1027                  /* Instance.flags */
1028                  if (batch != batch_)
1029                  {
1030                      inst->releaseBatch = MI_TRUE;
1031                  }
1032              
1033                  /* Set Instance.batch */
1034                  inst->batch = batch;
1035              
1036 mike     1.1     /* Set MI_Instance.ft */
1037                  inst->ft = &__mi_instanceFT;
1038              
1039                  /* Instance.nameSpace */
1040                  if (self->nameSpace)
1041                  {
1042                      inst->nameSpace = BStrdup(batch, self->nameSpace, CALLSITE);
1043              
1044                      if (!inst->nameSpace)
1045                      {
1046                          r = MI_RESULT_FAILED;
1047                          goto failed;
1048                      }
1049                  }
1050              
1051                  /* Instance.serverName */
1052                  if (self->serverName)
1053                  {
1054                      inst->serverName = BStrdup(batch, self->serverName, CALLSITE);
1055              
1056                      if (!inst->serverName)
1057 mike     1.1         {
1058                          r = MI_RESULT_FAILED;
1059                          goto failed;
1060                      }
1061                  }
1062              
1063                  /* Set Instance.classDecl */
1064 krisbash 1.4     if ((self->classDecl->flags & (MI_FLAG_CLASS|MI_FLAG_INDICATION|MI_FLAG_ASSOCIATION)) &&  (self->classDecl->owningClass == NULL)) //static
1065                  {
1066                      inst->classDecl = self->classDecl;
1067                  }
1068                  else if ((self->classDecl->owningClass == (MI_Class*)-1) || !(self->classDecl->flags & (MI_FLAG_CLASS|MI_FLAG_INDICATION|MI_FLAG_ASSOCIATION)))
1069 mike     1.1     {
1070 krisbash 1.4         //classDecl is from a dynamic instance without a proper classDecl
1071 mike     1.1         inst->classDecl = _CloneClassDecl(self->classDecl, batch);
1072              
1073                      if (!inst->classDecl)
1074 krisbash 1.4             MI_RETURN(MI_RESULT_FAILED);
1075                  }
1076                  else if (self->classDecl->owningClass)  //has a proper MI_Class owner so can clone it to bump refcount
1077                  {
1078                      MI_Class *clonedClass;
1079                      MI_Result result = MI_Class_Clone(self->classDecl->owningClass, &clonedClass);
1080                      if (result != MI_RESULT_OK)
1081                          MI_RETURN(result);
1082                      inst->classDecl = clonedClass->classDecl;
1083                  }
1084                  else//We had better do a hard clone
1085                  {
1086                      inst->classDecl = Class_Clone_ClassDecl(batch, self->classDecl);
1087                      if (inst->classDecl == NULL)
1088                          MI_RETURN(MI_RESULT_FAILED);
1089 mike     1.1     }
1090              
1091                  /* Clone each of the fields */
1092                  for (i = 0; i < self->classDecl->numProperties; i++)
1093                  {
1094                      const MI_PropertyDecl* pd = self->classDecl->properties[i];
1095              
1096                      r = Field_Copy(
1097                          (Field*)((char*)inst + pd->offset),
1098                          pd->type,
1099                          (Field*)((char*)self + pd->offset),
1100                          batch);
1101              
1102                      if (r != MI_RESULT_OK)
1103                      {
1104                          r = MI_RESULT_FAILED;
1105                          goto failed;
1106                      }
1107                  }
1108              
1109                  /* Wrapper dynamic instances */
1110 mike     1.1     if ((void*)self != (void*)self_)
1111                  {
1112                      inst = _WrapInstance(inst, batch);
1113                      if (!inst)
1114                      {
1115                          r = MI_RESULT_FAILED;
1116                          goto failed;
1117                      }
1118                  }
1119              
1120                  *instOut = (MI_Instance*)inst;
1121                  return MI_RESULT_OK;
1122              
1123              failed:
1124                  if (batch != batch_)
1125                      Batch_Delete(batch);
1126                  return r;
1127              }
1128              
1129              MI_Result MI_CALL Instance_SetClassName(
1130 krisbash 1.5     MI_Instance* self_,
1131 krisbash 1.4     const ZChar* className)
1132 mike     1.1 {
1133                  Instance* self = _SelfOf(self_);
1134 krisbash 1.4     ZChar* oldClassName;
1135 mike     1.1 
1136                  /* Check parameters */
1137                  if (!self || !className)
1138                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1139              
1140                  /* Save old className */
1141                  oldClassName = self->classDecl->name;
1142              
1143                  /* Set new className */
1144                  {
1145 krisbash 1.4         ZChar* tmp = BStrdup(self->batch, className, CALLSITE);
1146 mike     1.1 
1147                      if (!tmp)
1148                          MI_RETURN(MI_RESULT_FAILED);
1149              
1150                      self->classDecl->name = tmp;
1151 krisbash 1.4         self->classDecl->code = Hash(tmp);
1152 mike     1.1     }
1153              
1154                  /* Free old className */
1155                  if (oldClassName)
1156                      BFree(self->batch, oldClassName, CALLSITE);
1157              
1158                  MI_RETURN(MI_RESULT_OK);
1159              }
1160              
1161 krisbash 1.4 _Use_decl_annotations_
1162 mike     1.1 MI_Result MI_CALL Instance_NewDynamic(
1163                  MI_Instance** selfOut,
1164 krisbash 1.4     const ZChar* className,
1165 mike     1.1     MI_Uint32 metaType,
1166                  Batch* batch_)
1167              {
1168                  Instance* self = NULL;
1169                  Batch* batch = batch_;
1170                  MI_Result r;
1171              
1172                  /* Reject null arguments */
1173                  if (!selfOut || !className)
1174                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1175              
1176                  /* Null output self pointer */
1177                  *selfOut = NULL;
1178              
1179                  /* Create batch if necessary */
1180                  if (!batch)
1181                  {
1182                      batch = Batch_New(_NUM_PAGES);
1183                      if (!batch)
1184                          return MI_RESULT_FAILED;
1185                  }
1186 mike     1.1 
1187                  /* Check that 'className' parameter is a legal CIM className */
1188                  if (!LegalName(className))
1189                  {
1190                      r = MI_RESULT_INVALID_PARAMETER;
1191                      goto failed;
1192                  }
1193              
1194                  /* Allocate instance and reserve room for properties */
1195                  {
1196 krisbash 1.5         self = _AllocInstance(batch,
1197 mike     1.1             sizeof(MI_Instance) + _CAPACITY * sizeof(Field));
1198              
1199                      if (!self)
1200                      {
1201                          r = MI_RESULT_FAILED;
1202                          goto failed;
1203                      }
1204              
1205                      self->self = self;
1206                  }
1207              
1208                  /* Set Instance.classDecl */
1209                  {
1210                      MI_ClassDecl* cd;
1211              
1212                      /* Allocate and set Instance.classDecl */
1213                      {
1214                          cd = (MI_ClassDecl*)BCalloc(batch, sizeof(MI_ClassDecl), CALLSITE);
1215              
1216                          if (!cd)
1217                          {
1218 mike     1.1                 r = MI_RESULT_FAILED;
1219                              goto failed;
1220                          }
1221              
1222 krisbash 1.4             cd->owningClass = (MI_Class*) -1; /* Mark as a dynamic instance */
1223 mike     1.1             self->classDecl = cd;
1224                      }
1225 krisbash 1.5 
1226 mike     1.1         /* MI_ClassDecl.flags: */
1227                      if (metaType & MI_FLAG_ASSOCIATION)
1228                          cd->flags |= MI_FLAG_ASSOCIATION;
1229                      else if (metaType & MI_FLAG_INDICATION)
1230                          cd->flags |= MI_FLAG_INDICATION;
1231                      else if (metaType & MI_FLAG_METHOD)
1232                          cd->flags |= MI_FLAG_METHOD;
1233                      else if (metaType & MI_FLAG_CLASS)
1234                          cd->flags |= MI_FLAG_CLASS;
1235                      else
1236                          cd->flags |= MI_FLAG_CLASS;
1237              
1238                      /* MI_ClassDecl.name: */
1239                      {
1240                          cd->name = BStrdup(batch, className, CALLSITE);
1241              
1242                          if (!cd->name)
1243                          {
1244                              r = MI_RESULT_FAILED;
1245                              goto failed;
1246                          }
1247 krisbash 1.4 
1248 mike     1.1         }
1249              
1250                      /* MI_ClassDecl.code: */
1251 krisbash 1.4         cd->code = Hash(cd->name);
1252 mike     1.1 
1253                      /* MI_ClassDecl.properties: */
1254                      {
1255                          MI_PropertyDecl** data;
1256              
1257                          data = (MI_PropertyDecl**)BAlloc(batch,
1258                              _CAPACITY * sizeof(MI_PropertyDecl), CALLSITE);
1259              
1260                          if (!data)
1261                          {
1262                              r = MI_RESULT_FAILED;
1263                              goto failed;
1264                          }
1265              
1266                          cd->properties = data;
1267                          cd->numProperties = 0;
1268                      }
1269              
1270                      /* MI_ClassDecl.size: */
1271                      cd->size = sizeof(MI_Instance);
1272                  }
1273 mike     1.1 
1274                  /* Set batch: */
1275                  self->batch = batch;
1276              
1277                  /* Set flags */
1278                  if (batch_)
1279                      self->releaseBatch = MI_FALSE;
1280                  else
1281                      self->releaseBatch = MI_TRUE;
1282              
1283                  /* Set MI_Instance.ft: */
1284                  self->ft = &__mi_instanceFT;
1285              
1286                  /* Set the self pointer */
1287                  self->self = self;
1288              
1289                  /* Set output instance (creating a wrapper for it) */
1290                  self = _WrapInstance(self, batch);
1291                  if (!self)
1292                  {
1293                      r = MI_RESULT_FAILED;
1294 mike     1.1         goto failed;
1295                  }
1296              
1297                  *selfOut = (MI_Instance*)self;
1298                  MI_RETURN(MI_RESULT_OK);
1299              
1300              failed:
1301                  if (batch != batch_)
1302                      Batch_Delete(batch);
1303                  return r;
1304              }
1305              
1306              MI_Boolean Instance_MatchKeys(
1307                  const MI_Instance* self_,
1308                  const MI_Instance* inst_)
1309              {
1310                  Instance* self;
1311                  Instance* inst;
1312              
1313                  /* Check parameters */
1314                  if (!self_ || !inst_)
1315 mike     1.1     {
1316                      return MI_FALSE;
1317                  }
1318              
1319                  self = _SelfOf(self_);
1320                  inst = _SelfOf(inst_);
1321              
1322                  /* Check parameters */
1323                  if (!self || !inst)
1324                  {
1325                      return MI_FALSE;
1326                  }
1327              
1328                  /* Verify they have the same number of keys (one or more) */
1329                  {
1330                      MI_Uint32 n = _CountKeys(self);
1331              
1332                      if (n == 0 || n != _CountKeys(inst))
1333                      {
1334                          return MI_FALSE;
1335                      }
1336 mike     1.1     }
1337              
1338                  /* Verify that key fields are identical */
1339                  {
1340                      const MI_ClassDecl* cd1 = self->classDecl;
1341                      const MI_ClassDecl* cd2 = inst->classDecl;
1342                      MI_Uint32 i;
1343              
1344                      for (i = 0; i < cd1->numProperties; i++)
1345                      {
1346                          const MI_PropertyDecl* pd1 = cd1->properties[i];
1347                          const MI_PropertyDecl* pd2;
1348                          Field* f1;
1349                          Field* f2;
1350                          MI_Uint32 index;
1351              
1352                          if (pd1->flags & MI_FLAG_KEY)
1353                          {
1354                              index = _FindPropertyDecl(cd2, pd1->name);
1355              
1356                              if (index == (MI_Uint32)-1)
1357 mike     1.1                 {
1358                                  return MI_FALSE;
1359                              }
1360              
1361                              pd2 = cd2->properties[index];
1362              
1363                              if (!(pd2->flags & MI_FLAG_KEY))
1364                              {
1365                                  return MI_FALSE;
1366                              }
1367              
1368                              if (pd1->type != pd2->type)
1369                                  return MI_FALSE;
1370              
1371                              f1 = (Field*)((char*)self + pd1->offset);
1372                              f2 = (Field*)((char*)inst + pd2->offset);
1373              
1374                              if (!Field_MatchKey(f1, f2, pd1->type))
1375                              {
1376                                  return MI_FALSE;
1377                              }
1378 mike     1.1             }
1379                      }
1380                  }
1381              
1382                  return MI_TRUE;
1383              }
1384              
1385 krisbash 1.4 /* Get underline instance */
1386              Instance* Instance_GetSelf(
1387                  const MI_Instance* self)
1388              {
1389                  return _SelfOf( self );
1390              }
1391              
1392 mike     1.1 /*
1393              **==============================================================================
1394              **
1395              ** MI_Instance function table and functions
1396              **
1397              **==============================================================================
1398              */
1399              
1400              void __MI_Instance_Ref(MI_Instance* self)
1401              {
1402                  InstanceHeader* h = _HeaderOf((Instance*)self);
1403              
1404                  if (h)
1405 krisbash 1.4         Atomic_Inc(&h->u.refs);
1406 mike     1.1 }
1407              
1408              void __MI_Instance_Unref(MI_Instance* self)
1409              {
1410                  InstanceHeader* h = _HeaderOf((Instance*)self);
1411              
1412 krisbash 1.4     if (h && Atomic_Dec(&h->u.refs) == 0)
1413 mike     1.1         __MI_Instance_Delete((MI_Instance*)self);
1414              }
1415              
1416              MI_Result MI_CALL __MI_Instance_Clone(
1417 krisbash 1.5     const MI_Instance* self,
1418 mike     1.1     MI_Instance** inst)
1419              {
1420                  return Instance_Clone(self, inst, NULL);
1421              }
1422              
1423              MI_Result MI_CALL __MI_Instance_Destruct(
1424                  MI_Instance* self_)
1425              {
1426                  Instance* self = _SelfOf(self_);
1427                  Batch* batch;
1428                  MI_Uint32 i;
1429 krisbash 1.4     MI_Boolean releaseBatch;
1430 mike     1.1 
1431                  /* Check for null parameter */
1432                  if (!self)
1433                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1434              
1435 krisbash 1.4     /* Save release flag */
1436                  releaseBatch = self->releaseBatch;
1437              
1438 mike     1.1     /* Save pointer to batch */
1439                  batch = self->batch;
1440                  if (!batch)
1441                      MI_RETURN(MI_RESULT_FAILED);
1442              
1443                  /* Release serverName */
1444                  if (self->serverName)
1445                      BFree(batch, self->serverName, CALLSITE);
1446              
1447                  /* Release nameSpace */
1448                  if (self->nameSpace)
1449                      BFree(batch, self->nameSpace, CALLSITE);
1450              
1451                  /* Release all memory used by properties */
1452                  for (i = 0; i < self->classDecl->numProperties; i++)
1453                  {
1454                      const MI_PropertyDecl* pd = self->classDecl->properties[i];
1455                      Field* field = (Field*)((char*)self + pd->offset);
1456                      Field_Destruct(field, pd->type, batch);
1457                  }
1458              
1459 mike     1.1     /* Free dynamic instance part (if any) */
1460                  if ((void*)self != (void*)self_)
1461                  {
1462                      for (i = 0; i < self->classDecl->numProperties; i++)
1463                      {
1464                          MI_PropertyDecl* pd = self->classDecl->properties[i];
1465                          BFree(batch, pd->name, CALLSITE);
1466                          BFree(batch, pd, CALLSITE);
1467                      }
1468              
1469                      BFree(batch, self->classDecl->name, CALLSITE);
1470                      BFree(batch, self->classDecl->properties, CALLSITE);
1471                      BFree(batch, self->classDecl, CALLSITE);
1472              
1473                      if ((void*)self != (void*)self_)
1474                          _FreeInstance(batch, self);
1475                  }
1476 krisbash 1.4     else
1477                  {
1478                      if ((self->classDecl->flags & (MI_FLAG_CLASS|MI_FLAG_INDICATION|MI_FLAG_ASSOCIATION)) && self->classDecl->owningClass)
1479                      {
1480                          //Bump down the ref-count on the owning MI_Class if there is one, deleting it if necessary
1481                          MI_Class_Delete(self->classDecl->owningClass);
1482                      }
1483                  }
1484              
1485                  /* release batch */
1486                  if (releaseBatch)
1487                      Batch_Delete(batch);
1488 mike     1.1 
1489                  MI_RETURN(MI_RESULT_OK);
1490              }
1491              
1492              MI_Result MI_CALL __MI_Instance_Delete(
1493                  MI_Instance* self_)
1494              {
1495                  Instance* self = _SelfOf(self_);
1496                  MI_Result r;
1497                  Batch* batch;
1498                  MI_Boolean releaseBatch;
1499              
1500                  /* Check for null parameter */
1501                  if (!self)
1502                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1503              
1504                  /* Save pointer to batch */
1505                  batch = self->batch;
1506                  if (!batch)
1507                      MI_RETURN(MI_RESULT_FAILED);
1508              
1509 mike     1.1     /* Save */
1510                  releaseBatch = self->releaseBatch;
1511              
1512                  /* Destruct */
1513                  r = __MI_Instance_Destruct(self_);
1514                  if (r != MI_RESULT_OK)
1515                      MI_RETURN(r);
1516              
1517                  /* Release self pointer */
1518 krisbash 1.4     if (MI_FALSE == releaseBatch)
1519                      _FreeInstance(batch, (Instance*)self_);
1520 mike     1.1 
1521                  return r;
1522              }
1523              
1524              MI_Result MI_CALL __MI_Instance_IsA(
1525                  const MI_Instance* self_,
1526                  const MI_ClassDecl* classDecl,
1527                  MI_Boolean* resultOut)
1528              {
1529                  Instance* self = _SelfOf(self_);
1530                  const MI_ClassDecl* p;
1531              
1532                  if (!self || !classDecl)
1533                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1534              
1535                  for (p = self->classDecl; p; p = p->superClassDecl)
1536                  {
1537                      if (p == classDecl)
1538                      {
1539                          if (resultOut)
1540                              *resultOut = MI_TRUE;
1541 mike     1.1             MI_RETURN(MI_RESULT_OK);
1542                      }
1543                  }
1544              
1545                  if (resultOut)
1546                      *resultOut = MI_FALSE;
1547              
1548                  MI_RETURN(MI_RESULT_OK);
1549              }
1550              
1551              MI_Result MI_CALL __MI_Instance_GetClassName(
1552 krisbash 1.5     const MI_Instance* self_,
1553 krisbash 1.4     const ZChar** classNameOut)
1554 mike     1.1 {
1555                  Instance* self = _SelfOf(self_);
1556              
1557                  if (!self)
1558                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1559              
1560                  if (classNameOut)
1561                      *classNameOut = self->classDecl->name;
1562              
1563                  MI_RETURN(MI_RESULT_OK);
1564              }
1565              
1566              MI_Result MI_CALL __MI_Instance_SetNameSpace(
1567 krisbash 1.5     MI_Instance* self_,
1568 krisbash 1.4     const ZChar* nameSpace)
1569 mike     1.1 {
1570                  Instance* self = _SelfOf(self_);
1571 krisbash 1.4     ZChar* oldNameSpace;
1572 mike     1.1 
1573                  /* Check parameters */
1574                  if (!self)
1575                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1576              
1577                  /* Save old namespace */
1578                  oldNameSpace = self->nameSpace;
1579              
1580                  /* Set new namespace */
1581                  if (nameSpace)
1582                  {
1583 krisbash 1.4         ZChar* tmp = BStrdup(self->batch, nameSpace, CALLSITE);
1584 mike     1.1 
1585                      if (!tmp)
1586                          MI_RETURN(MI_RESULT_FAILED);
1587              
1588                      self->nameSpace = tmp;
1589                  }
1590                  else
1591                      self->nameSpace = NULL;
1592              
1593                  /* Free old namespace */
1594                  if (oldNameSpace)
1595                      BFree(self->batch, oldNameSpace, CALLSITE);
1596              
1597                  MI_RETURN(MI_RESULT_OK);
1598              }
1599              
1600              MI_Result MI_CALL __MI_Instance_GetNameSpace(
1601 krisbash 1.5     const MI_Instance* self_,
1602 krisbash 1.4     const ZChar** nameSpaceOut)
1603 mike     1.1 {
1604                  Instance* self = _SelfOf(self_);
1605              
1606                  if (!self)
1607                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1608              
1609                  if (nameSpaceOut)
1610                      *nameSpaceOut = self->nameSpace;
1611              
1612                  MI_RETURN(MI_RESULT_OK);
1613              }
1614              
1615              MI_Result MI_CALL __MI_Instance_GetElementCount(
1616                  const MI_Instance* self_,
1617                  MI_Uint32* countOut)
1618              {
1619                  Instance* self = _SelfOf(self_);
1620              
1621                  if (!self)
1622                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1623              
1624 mike     1.1     if (countOut)
1625                      *countOut = self->classDecl->numProperties;
1626              
1627                  MI_RETURN(MI_RESULT_OK);
1628              }
1629              
1630              MI_Result MI_CALL __MI_Instance_AddElement(
1631                  MI_Instance* self_,
1632 krisbash 1.4     const ZChar* name,
1633 mike     1.1     const MI_Value* value,
1634                  MI_Type type,
1635                  MI_Uint32 flags)
1636              {
1637                  Instance* self = _SelfOf(self_);
1638                  MI_Uint32 index;
1639                  MI_ClassDecl* cd;
1640                  MI_Uint32 tflags = 0;
1641              
1642                  if (flags & MI_FLAG_BORROW)
1643                      tflags |= MI_FLAG_BORROW;
1644              
1645                  if (flags & MI_FLAG_NULL)
1646                      tflags |= MI_FLAG_NULL;
1647              
1648                  /* Check for null arguments */
1649                  if (!self || !name)
1650                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1651              
1652                  /* Reject attempts to extend a non-dynamic instances */
1653                  if ((void*)self == (void*)self_)
1654 mike     1.1         MI_RETURN(MI_RESULT_FAILED);
1655              
1656                  /* Check that 'name' parameter is a legal CIM name */
1657                  if (!LegalName(name))
1658                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1659              
1660                  /* Find the property with this name */
1661                  index = _FindPropertyDecl(self->classDecl, name);
1662              
1663                  if (index != (MI_Uint32)-1)
1664                      MI_RETURN(MI_RESULT_ALREADY_EXISTS);
1665              
1666                  /* Get pointer to class declaration */
1667                  cd = (MI_ClassDecl*)self->classDecl;
1668              
1669                  /* Extend size of instance and properties array as needed */
1670                  if (cd->numProperties == _FindCapacity(cd->numProperties))
1671                  {
1672                      MI_Uint32 cap;
1673                      MI_PropertyDecl** data;
1674              
1675 mike     1.1         /* Double old capacity */
1676                      cap = 2 * cd->numProperties;
1677              
1678                      /* Reallocate properties array */
1679                      data = (MI_PropertyDecl**)BRealloc(
1680 krisbash 1.5             self->batch,
1681                          cd->properties,
1682 krisbash 1.4             cd->numProperties * sizeof(MI_PropertyDecl*),
1683                          cap * sizeof(MI_PropertyDecl*),
1684 mike     1.1             CALLSITE);
1685              
1686                      if (!data)
1687                          MI_RETURN(MI_RESULT_FAILED);
1688              
1689                      cd->properties = data;
1690 krisbash 1.5 
1691 mike     1.1         /* Reallocate instance */
1692                      self = _ReallocInstance(
1693 krisbash 1.5             self->batch,
1694                          self,
1695 mike     1.1             sizeof(MI_Instance) + cd->numProperties * sizeof(Field),
1696                          sizeof(MI_Instance) + cap * sizeof(Field));
1697                      if (!self)
1698                          MI_RETURN(MI_RESULT_FAILED);
1699              
1700                      /* Set new self */
1701                      self->self = self;
1702                  }
1703              
1704                  /* Create and add new property */
1705                  {
1706                      MI_PropertyDecl* pd;
1707              
1708                      /* Allocate new peroperty declaration */
1709                      pd = (MI_PropertyDecl*)BCalloc(
1710                          self->batch, sizeof(MI_PropertyDecl), CALLSITE);
1711              
1712                      if (!pd)
1713                          MI_RETURN(MI_RESULT_FAILED);
1714              
1715                      /* MI_PropertyDecl.flags */
1716 mike     1.1         pd->flags = flags;
1717              
1718                      /* MI_PropertyDecl.name */
1719                      pd->name = BStrdup(self->batch, name, CALLSITE);
1720              
1721                      if (!pd->name)
1722                          MI_RETURN(MI_RESULT_FAILED);
1723              
1724 krisbash 1.4         /* MI_PropertyDecl.code */
1725                      pd->code = Hash(pd->name);
1726              
1727 mike     1.1         /* MI_PropertyDecl.type */
1728                      pd->type = type;
1729              
1730                      /* MI_PropertyDecl.offset */
1731                      pd->offset = sizeof(MI_Instance) + cd->numProperties*sizeof(Field);
1732              
1733                      /* Add property to array */
1734                      cd->properties[cd->numProperties++] = pd;
1735 krisbash 1.5 
1736 mike     1.1         /* Clear the new field */
1737                      memset((char*)self + pd->offset, 0, sizeof(Field));
1738              
1739                      /* Adjust size */
1740                      cd->size += sizeof(Field);
1741                  }
1742              
1743                  /* Reassign 'self' field (it may have changed) */
1744                  ((Instance*)self_)->self = self;
1745              
1746                  /* Copy self of self wrapper */
1747                  memcpy(self_, self, sizeof(MI_Instance));
1748              
1749                  /* Set the last property */
1750                  MI_RETURN(__MI_Instance_SetElementAt(
1751                      self_, cd->numProperties - 1, value, type, tflags));
1752              }
1753              
1754              MI_Result MI_CALL __MI_Instance_SetElement(
1755 krisbash 1.5     MI_Instance* self_,
1756                  const ZChar* name,
1757 mike     1.1     const MI_Value* value,
1758                  MI_Type type,
1759                  MI_Uint32 flags)
1760              {
1761                  Instance* self = _SelfOf(self_);
1762                  MI_Uint32 index;
1763              
1764                  /* Check for null arguments */
1765                  if (!self || !name)
1766                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1767              
1768                  /* Find the property with this name */
1769                  index = _FindPropertyDecl(self->classDecl, name);
1770              
1771                  if (index == (MI_Uint32)-1)
1772                      MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
1773              
1774                  MI_RETURN(__MI_Instance_SetElementAt(self_, index, value, type, flags));
1775              }
1776              
1777              MI_Result MI_CALL __MI_Instance_SetElementAt(
1778 krisbash 1.5     MI_Instance* self_,
1779 mike     1.1     MI_Uint32 index,
1780                  const MI_Value* value,
1781                  MI_Type type,
1782                  MI_Uint32 flags)
1783              {
1784                  Instance* self = _SelfOf(self_);
1785                  const MI_PropertyDecl* pd;
1786                  char* field;
1787              
1788                  /* Check for null arguments */
1789                  if (!self)
1790                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1791 krisbash 1.5 
1792 mike     1.1     /* Check whether index is in range */
1793                  if (index > self->classDecl->numProperties)
1794                      MI_RETURN(MI_RESULT_FAILED);
1795              
1796                  /* Get pointer to properties declaration */
1797                  pd = self->classDecl->properties[index];
1798              
1799                  /* Check the type */
1800                  if (type != (MI_Type)pd->type)
1801                      MI_RETURN(MI_RESULT_TYPE_MISMATCH);
1802              
1803                  /* Get pointer to field */
1804                  field = (char*)self + pd->offset;
1805              
1806                  /* Set the value */
1807                  {
1808                      MI_Result r = Field_Set(
1809 krisbash 1.4             (Field*)field,
1810 mike     1.1             pd->type,
1811                          value,
1812                          flags,
1813                          self->batch);
1814              
1815                      if (r != MI_RESULT_OK)
1816                          return r;
1817                  }
1818              
1819                  MI_RETURN(MI_RESULT_OK);
1820              }
1821              
1822              MI_Result MI_CALL __MI_Instance_GetElement(
1823 krisbash 1.5     const MI_Instance* self_,
1824                  const ZChar* name,
1825 mike     1.1     MI_Value* valueOut,
1826                  MI_Type* typeOut,
1827                  MI_Uint32* flagsOut,
1828                  MI_Uint32* indexOut)
1829              {
1830                  Instance* self = _SelfOf(self_);
1831                  MI_Uint32 index;
1832                  MI_Result r;
1833              
1834                  /* Check for null arguments */
1835                  if (!self || !name)
1836                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1837              
1838                  /* Find the property with this name */
1839                  index = _FindPropertyDecl(self->classDecl, name);
1840              
1841                  if (index == (MI_Uint32)-1)
1842                      MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
1843              
1844                  r = __MI_Instance_GetElementAt(
1845                      self_, index, NULL, valueOut, typeOut, flagsOut);
1846 mike     1.1 
1847                  if (r != MI_RESULT_OK)
1848                      MI_RETURN(r);
1849              
1850                  if (indexOut)
1851                      *indexOut = index;
1852              
1853                  MI_RETURN(MI_RESULT_OK);
1854              }
1855              
1856              MI_Result MI_CALL __MI_Instance_GetElementAt(
1857                  const MI_Instance* self_,
1858                  MI_Uint32 index,
1859 krisbash 1.4     const ZChar** nameOut,
1860 mike     1.1     MI_Value* valueOut,
1861                  MI_Type* typeOut,
1862                  MI_Uint32* flagsOut)
1863              {
1864                  Instance* self = _SelfOf(self_);
1865                  const MI_PropertyDecl* pd;
1866                  const Field* field;
1867              
1868                  /* Check for null arguments */
1869                  if (!self)
1870                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1871              
1872                  /* Check for bounds error */
1873                  if (index >= self->classDecl->numProperties)
1874                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1875              
1876                  pd = self->classDecl->properties[index];
1877              
1878                  /* Get pointer to field */
1879                  field = (Field*)((char*)self + pd->offset);
1880              
1881 mike     1.1     /* set nameOut */
1882                  if (nameOut)
1883                      *nameOut = pd->name;
1884              
1885                  /* set valueOut */
1886                  if (valueOut)
1887                      memcpy(valueOut, field, Type_SizeOf((MI_Type)pd->type));
1888              
1889 krisbash 1.4     /* Set flagsOut */
1890 mike     1.1     if (flagsOut)
1891                  {
1892 krisbash 1.4         MI_Uint8 fieldFlags = 0;
1893                      *flagsOut = pd->flags & ~(MI_FLAG_NULL | MI_FLAG_NOT_MODIFIED);
1894 mike     1.1 
1895                      if (!Field_GetExists(field, (MI_Type)pd->type))
1896                          *flagsOut |= MI_FLAG_NULL;
1897 krisbash 1.4 
1898                      /* get the field flags */
1899                      switch ((MI_Type)pd->type)
1900                      {
1901                          case MI_UINT8:
1902                          case MI_SINT8:
1903                          case MI_BOOLEAN:
1904                          {
1905                              MI_Uint8Field* f = (MI_Uint8Field*)field;
1906                              fieldFlags = f->flags;
1907                              break;
1908                          }
1909                          case MI_UINT16:
1910                          case MI_SINT16:
1911                          case MI_CHAR16:
1912                          {
1913                              MI_Uint16Field* f = (MI_Uint16Field*)field;
1914                              fieldFlags = f->flags;
1915                              break;
1916                          }
1917                          case MI_UINT32:
1918 krisbash 1.4             case MI_SINT32:
1919                          case MI_REAL32:
1920                          {
1921                              MI_Uint32Field* f = (MI_Uint32Field*)field;
1922                              fieldFlags = f->flags;
1923                              break;
1924                          }
1925                          case MI_UINT64:
1926                          case MI_SINT64:
1927                          case MI_REAL64:
1928                          {
1929                              MI_Uint64Field* f = (MI_Uint64Field*)field;
1930                              fieldFlags = f->flags;
1931                              break;
1932                          }
1933                          case MI_DATETIME:
1934                          {
1935                              MI_DatetimeField* f = (MI_DatetimeField*)field;
1936                              fieldFlags = f->flags;
1937                              break;
1938                          }
1939 krisbash 1.4             case MI_STRING:
1940                          {
1941                              MI_StringField* f = (MI_StringField*)field;
1942                              fieldFlags = f->flags;
1943                              break;
1944                          }
1945                          case MI_INSTANCE:
1946                          case MI_REFERENCE:
1947                          {
1948                              MI_InstanceField* f = (MI_InstanceField*)field;
1949                              fieldFlags = f->flags;
1950                              break;
1951                          }
1952                          case MI_BOOLEANA:
1953                          case MI_UINT8A:
1954                          case MI_SINT8A:
1955                          case MI_UINT16A:
1956                          case MI_SINT16A:
1957                          case MI_UINT32A:
1958                          case MI_SINT32A:
1959                          case MI_UINT64A:
1960 krisbash 1.4             case MI_SINT64A:
1961                          case MI_REAL32A:
1962                          case MI_REAL64A:
1963                          case MI_CHAR16A:
1964                          case MI_DATETIMEA:
1965                          case MI_INSTANCEA:
1966                          case MI_REFERENCEA:
1967                          case MI_STRINGA:
1968                          {
1969                              MI_StringAField* f = (MI_StringAField*)field;
1970                              fieldFlags = f->flags;
1971                              break;
1972                          }
1973                      }
1974                      if ((fieldFlags & _MODIFIED) == 0)
1975                      {
1976                          *flagsOut |= MI_FLAG_NOT_MODIFIED;
1977                      }
1978 mike     1.1     }
1979              
1980                  /* Set typeOut */
1981                  if (typeOut)
1982                      *typeOut = (MI_Type)pd->type;
1983              
1984                  MI_RETURN(MI_RESULT_OK);
1985              }
1986              
1987              MI_Result MI_CALL __MI_Instance_ClearElement(
1988 krisbash 1.5     MI_Instance* self_,
1989 krisbash 1.4     const ZChar* name)
1990 mike     1.1 {
1991                  Instance* self = _SelfOf(self_);
1992                  MI_Uint32 index;
1993              
1994                  /* Check for null arguments */
1995                  if (!self || !name)
1996                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1997              
1998                  /* Find the property with this name */
1999                  index = _FindPropertyDecl(self->classDecl, name);
2000              
2001                  if (index == (MI_Uint32)-1)
2002                      MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
2003              
2004                  MI_RETURN(__MI_Instance_ClearElementAt(self_, index));
2005              }
2006              
2007              MI_Result MI_CALL __MI_Instance_ClearElementAt(
2008 krisbash 1.5     MI_Instance* self_,
2009 mike     1.1     MI_Uint32 index)
2010              {
2011                  Instance* self = _SelfOf(self_);
2012                  const MI_PropertyDecl* pd;
2013                  char* field;
2014              
2015                  /* Check for null arguments */
2016                  if (!self)
2017                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
2018 krisbash 1.5 
2019 mike     1.1     /* Check whether index is in range */
2020                  if (index > self->classDecl->numProperties)
2021                      MI_RETURN(MI_RESULT_FAILED);
2022              
2023                  /* Get pointer to properties declaration */
2024                  pd = self->classDecl->properties[index];
2025              
2026                  /* Get pointer to field */
2027                  field = (char*)self + pd->offset;
2028              
2029                  /* Clear the value */
2030 krisbash 1.4     Field_Clear((Field*)field, pd->type,
2031 mike     1.1         self->batch);
2032              
2033                  MI_RETURN(MI_RESULT_OK);
2034              }
2035              
2036 krisbash 1.4 MI_Result MI_CALL __MI_Instance_GetServerName(
2037 mike     1.1     const MI_Instance* self_,
2038 krisbash 1.4     const ZChar** servername)
2039 mike     1.1 {
2040                  Instance* self = _SelfOf(self_);
2041              
2042                  if (!self)
2043                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
2044              
2045 krisbash 1.4     if (servername)
2046                      *servername = self->serverName;
2047              
2048                  MI_RETURN(MI_RESULT_OK);
2049              }
2050              
2051              MI_Result MI_CALL __MI_Instance_SetServerName(
2052                  _Inout_ MI_Instance* self_,
2053                  _In_z_ const ZChar* serverName)
2054              {
2055                  Instance* self = _SelfOf(self_);
2056                  Instance* selfOrg = (Instance*)self_;
2057                  MI_Char* oldServerName;
2058 mike     1.1 
2059 krisbash 1.4     /* Check parameters */
2060                  if (!self)
2061                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
2062 mike     1.1 
2063 krisbash 1.4     /* Save old namespace */
2064                  oldServerName = self->serverName;
2065 mike     1.1 
2066 krisbash 1.4     /* Set new namespace */
2067                  if (serverName)
2068                  {
2069                      MI_Char* tmp;
2070 mike     1.1 
2071 krisbash 1.4         tmp = BStrdup(self->batch, serverName, CALLSITE);
2072 mike     1.1 
2073 krisbash 1.4         if (!tmp)
2074                          MI_RETURN(MI_RESULT_SERVER_LIMITS_EXCEEDED);
2075 mike     1.1 
2076 krisbash 1.4         self->serverName = tmp;
2077 mike     1.1     }
2078 krisbash 1.4     else
2079                      self->serverName = NULL;
2080 mike     1.1 
2081 krisbash 1.4     if (selfOrg != self)
2082                      selfOrg->serverName = self->serverName;
2083 mike     1.1 
2084 krisbash 1.4     /* Free old namespace */
2085                  if (oldServerName)
2086                      BFree(self->batch, oldServerName, CALLSITE);
2087 mike     1.1 
2088                  MI_RETURN(MI_RESULT_OK);
2089              }
2090              
2091 krisbash 1.4 MI_Result MI_CALL __MI_Instance_GetClass(
2092                  _In_ const MI_Instance* self_,
2093                  _Outptr_ MI_Class** instanceClass)
2094              {
2095                  Instance* self = _SelfOf(self_);
2096              
2097                  return Class_New(self->classDecl, self->nameSpace, self->serverName, instanceClass);
2098              }
2099              
2100              MI_Result MI_CALL MI_Instance_GetClassExt(
2101 krisbash 1.5     _In_ const MI_Instance *self,
2102 krisbash 1.4     _Inout_ MI_Class* classToGet)
2103 mike     1.1 {
2104 krisbash 1.5     if ((self == NULL) || (classToGet == NULL))
2105 krisbash 1.4         MI_RETURN(MI_RESULT_INVALID_PARAMETER);
2106 krisbash 1.5 
2107 krisbash 1.4     return Class_Construct(classToGet, self->classDecl);
2108 mike     1.1 }
2109              
2110 krisbash 1.4 MI_Result Instance_SetElementArray(
2111 krisbash 1.5     _Out_ MI_Instance* self_,
2112 krisbash 1.4     _In_z_ const MI_Char* name,
2113                  MI_Type type,
2114                  MI_Uint32 flags,
2115                  MI_Uint32 numberArrayItems,
2116                  _Out_ MI_Uint32 *elementId
2117                  )
2118              {
2119                  MI_Result result;
2120                  Instance* self = _SelfOf(self_);
2121                  MI_Uint32 index;
2122                  MI_ArrayField *fieldValue;
2123                  MI_Value nullValue;
2124              
2125                  //Find the ID of the entry
2126                  /* Check for null arguments */
2127                  if (!self || !name)
2128                      MI_RETURN(MI_RESULT_INVALID_PARAMETER);
2129              
2130                  /* Find the property with this name */
2131                  index = _FindPropertyDeclIndex(self->classDecl, name);
2132              
2133 krisbash 1.4     if (index == (MI_Uint32)-1)
2134                      MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
2135              
2136                  //SetElementAt with NULL value
2137                  nullValue.array.data = NULL;
2138                  nullValue.array.size = 0;
2139                  result = __MI_Instance_SetElementAt(self_, index, &nullValue, type|MI_ARRAY, flags);
2140                  if (result != MI_RESULT_OK)
2141                  {
2142                      return result;
2143                  }
2144              
2145                  //Get the array field
2146                  fieldValue = (MI_ArrayField*)((char*)self + self->classDecl->properties[index]->offset);
2147              
2148                  //Allocate the element array
2149                  fieldValue->value.size = 0;  //We set the size as 0, but as items are added the number is increased
2150                  if (numberArrayItems)
2151                  {
2152                      fieldValue->value.data = Batch_Get(self->batch, numberArrayItems*Type_SizeOf(type));
2153                      if (fieldValue->value.data == NULL)
2154 krisbash 1.4         {
2155                          return MI_RESULT_SERVER_LIMITS_EXCEEDED;
2156                      }
2157                  }
2158                  else
2159                  {
2160                      fieldValue->value.data = NULL;
2161                  }
2162                  *elementId = index;
2163                  return MI_RESULT_OK;
2164              }
2165              
2166              MI_Result Instance_SetElementArrayItem(
2167                  _Out_ MI_Instance* self_,
2168 krisbash 1.5     MI_Uint32 elementId,
2169 krisbash 1.4     MI_Value value)
2170 mike     1.1 {
2171 krisbash 1.4     Instance* self = _SelfOf(self_);
2172                  MI_ArrayField *fieldValue;
2173 krisbash 1.5     MI_Type type;
2174 krisbash 1.4     MI_Result result;
2175              
2176                  type = (MI_Type)(self->classDecl->properties[elementId]->type & ~16); //Remove array part of type;
2177              
2178                  fieldValue = (MI_ArrayField*)((char*)self + self->classDecl->properties[elementId]->offset);
2179              
2180                  result = Class_Clone_ArrayValue(self->batch, type, fieldValue->value.data, fieldValue->value.size, &value);
2181                  if (result != MI_RESULT_OK)
2182                      return result;
2183              
2184                  //Bump how many array items we have in value
2185                  fieldValue->value.size++;
2186                  fieldValue->exists = MI_TRUE;
2187              
2188                  return MI_RESULT_OK;
2189 mike     1.1 }
2190              
2191 krisbash 1.4 MI_Boolean Instance_IsDynamic(
2192                  _In_ MI_Instance *self_)
2193 mike     1.1 {
2194 krisbash 1.4     Instance* self = _SelfOf(self_);
2195                  if (self != (void*)self_)
2196                      return MI_TRUE;
2197                  else
2198                      return MI_FALSE;
2199 mike     1.1 }
2200              
2201 krisbash 1.5 /*
2202 krisbash 1.4  * Verifies that all key properties of the instance have non-NULL values.  A
2203               * NULL key property means that it is a malformed instance.
2204               *
2205               * Note: __MI_Instance_* functions are used in case the provided instance
2206               *       does not have a function table.
2207               */
2208              MI_Boolean Instance_ValidateNonNullKeys(
2209                  const MI_Instance* self )
2210 mike     1.1 {
2211 krisbash 1.4     MI_Uint32 i = 0;
2212 krisbash 1.5 
2213 krisbash 1.4     if (Instance_IsDynamic((MI_Instance*)self))
2214                  {
2215                      /* Dynamic instance
2216 krisbash 1.5          * Since it doesn't have a MI_ClassDecl, the best we can do is to
2217 krisbash 1.4          * validate whether all of its key properties are non-NULL. */
2218                      MI_Uint32 count = 0;
2219                      MI_Result result = __MI_Instance_GetElementCount( self, &count );
2220                      if (MI_RESULT_OK != result)
2221                          return MI_FALSE;
2222                      for (i = 0; i < count; i++)
2223                      {
2224                          MI_Uint32 flags = 0;
2225                          MI_Result result = __MI_Instance_GetElementAt( self, i, NULL, NULL, NULL, &flags );
2226                          if (MI_RESULT_OK != result)
2227                              return MI_FALSE;
2228 krisbash 1.5             if ((MI_FLAG_KEY & flags) &&
2229 krisbash 1.4                 (MI_FLAG_NULL & flags))
2230                              return MI_FALSE;
2231                      }
2232                      return MI_TRUE;
2233                  }
2234                  else
2235                  {
2236                      /* Static instance
2237                       * Validate that each key property is non-NULL */
2238                      const MI_ClassDecl* cd = self->classDecl;
2239                      for (i = 0; i < cd->numProperties; i++)
2240                      {
2241                          if (cd->properties[i]->flags & MI_FLAG_KEY)
2242                          {
2243                              MI_Uint32 flags = 0;
2244                              MI_Result result = __MI_Instance_GetElementAt( self, i, NULL, NULL, NULL, &flags );
2245                              if (MI_RESULT_OK != result)
2246                                  return MI_FALSE;
2247                              if (MI_FLAG_NULL & flags)
2248                                  return MI_FALSE;
2249                          }
2250 krisbash 1.4         }
2251                      return MI_TRUE;
2252                  }
2253 mike     1.1 }
2254              
2255 krisbash 1.4 
2256 mike     1.1 MI_InstanceFT __mi_instanceFT =
2257              {
2258                  __MI_Instance_Clone,
2259                  __MI_Instance_Destruct,
2260                  __MI_Instance_Delete,
2261                  __MI_Instance_IsA,
2262                  __MI_Instance_GetClassName,
2263                  __MI_Instance_SetNameSpace,
2264                  __MI_Instance_GetNameSpace,
2265                  __MI_Instance_GetElementCount,
2266                  __MI_Instance_AddElement,
2267                  __MI_Instance_SetElement,
2268                  __MI_Instance_SetElementAt,
2269                  __MI_Instance_GetElement,
2270                  __MI_Instance_GetElementAt,
2271                  __MI_Instance_ClearElement,
2272                  __MI_Instance_ClearElementAt,
2273                  __MI_Instance_GetServerName,
2274                  __MI_Instance_SetServerName,
2275                  __MI_Instance_GetClass,
2276              };

ViewCVS 0.9.2