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