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 "packing.h"
26
27 /** Magic number for MI_Instance objects (binary buffer pack/unpack) */
28 #define INSTANCE_MAGIC ((MI_Uint32)0x462b9957)
29
30 /* The magic number that occurs at the end of an instance serialization */
31 static const MI_Uint32 _END_MAGIC = 0x76f474e3;
32
33 MI_INLINE void* _Alloc(Batch* batch, size_t size)
34 {
35 return batch ? Batch_Get(batch, size) : malloc(size);
36 }
37
38 /* Obtain the self pointer from this instance */
39 MI_INLINE Instance* _SelfOf(const MI_Instance* instance)
40 {
41 if (instance && ((Instance*)instance)->self)
42 return ((Instance*)instance)->self;
43 mike 1.1 else
44 return (Instance*)instance;
45 }
46
47 static MI_Result _PackField(Buf* buf, const void* field, MI_Type type)
48 {
49 switch (type)
50 {
51 case MI_BOOLEAN:
52 case MI_SINT8:
53 case MI_UINT8:
54 {
55 MI_Uint8Field* f = (MI_Uint8Field*)field;
56 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
57
58 if (f->exists)
59 MI_RETURN_ERR(Buf_PackU8(buf, f->value));
60 break;
61 }
62 case MI_SINT16:
63 case MI_UINT16:
64 mike 1.1 case MI_CHAR16:
65 {
66 MI_Uint16Field* f = (MI_Uint16Field*)field;
67 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
68
69 if (f->exists)
70 MI_RETURN_ERR(Buf_PackU16(buf, f->value));
71 break;
72 }
73 case MI_SINT32:
74 case MI_UINT32:
75 case MI_REAL32:
76 {
77 MI_Uint32Field* f = (MI_Uint32Field*)field;
78 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
79
80 if (f->exists)
81 MI_RETURN_ERR(Buf_PackU32(buf, f->value));
82 break;
83 }
84 case MI_SINT64:
85 mike 1.1 case MI_UINT64:
86 case MI_REAL64:
87 {
88 MI_Uint64Field* f = (MI_Uint64Field*)field;
89 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
90
91 if (f->exists)
92 MI_RETURN_ERR(Buf_PackU64(buf, f->value));
93 break;
94 }
95 case MI_DATETIME:
96 {
97 MI_DatetimeField* f = (MI_DatetimeField*)field;
98 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
99
100 if (f->exists)
101 Buf_PackDT(buf, &f->value);
102 break;
103 }
104 case MI_STRING:
105 {
106 mike 1.1 MI_StringField* f = (MI_StringField*)field;
107 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
108
109 if (f->exists)
110 MI_RETURN_ERR(Buf_PackStr(buf, f->value));
111 break;
112 }
113 case MI_INSTANCE:
114 case MI_REFERENCE:
115 {
116 MI_InstanceField* f = ((MI_InstanceField*)field);
117
118 if (f->exists && !f->value)
119 MI_RETURN(MI_RESULT_FAILED);
120
121 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
122
123 if (f->exists)
124 MI_RETURN_ERR(Instance_Pack(f->value, type == MI_REFERENCE,
125 NULL, NULL, buf));
126
127 mike 1.1 break;
128 }
129 case MI_BOOLEANA:
130 case MI_SINT8A:
131 case MI_UINT8A:
132 {
133 MI_Uint8AField* f = (MI_Uint8AField*)field;
134 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
135
136 if (f->exists)
137 {
138 if (!f->value.data)
139 MI_RETURN(MI_RESULT_FAILED);
140
141 MI_RETURN_ERR(Buf_PackU8A(buf, f->value.data,
142 f->value.size));
143 }
144 break;
145 }
146 case MI_SINT16A:
147 case MI_UINT16A:
148 mike 1.1 case MI_CHAR16A:
149 {
150 MI_Uint16AField* f = (MI_Uint16AField*)field;
151 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
152
153 if (f->exists)
154 {
155 if (!f->value.data)
156 MI_RETURN(MI_RESULT_FAILED);
157
158 MI_RETURN_ERR(Buf_PackU16A(buf, f->value.data,
159 f->value.size));
160 }
161 break;
162 }
163 case MI_SINT32A:
164 case MI_UINT32A:
165 case MI_REAL32A:
166 {
167 MI_Uint32AField* f = (MI_Uint32AField*)field;
168 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
169 mike 1.1
170 if (f->exists)
171 {
172 if (!f->value.data)
173 MI_RETURN(MI_RESULT_FAILED);
174
175 MI_RETURN_ERR(Buf_PackU32A(buf, f->value.data,
176 f->value.size));
177 }
178 break;
179 }
180 case MI_SINT64A:
181 case MI_UINT64A:
182 case MI_REAL64A:
183 {
184 MI_Uint64AField* f = (MI_Uint64AField*)field;
185 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
186
187 if (f->exists)
188 {
189 if (!f->value.data)
190 mike 1.1 MI_RETURN(MI_RESULT_FAILED);
191
192 MI_RETURN_ERR(Buf_PackU64A(buf, f->value.data,
193 f->value.size));
194 }
195 break;
196 }
197 case MI_DATETIMEA:
198 {
199 MI_DatetimeAField* f = (MI_DatetimeAField*)field;
200 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
201
202 if (f->exists)
203 {
204 if (!f->value.data)
205 MI_RETURN(MI_RESULT_FAILED);
206
207 MI_RETURN_ERR(Buf_PackDTA(buf, f->value.data,
208 f->value.size));
209 }
210 break;
211 mike 1.1 }
212 case MI_STRINGA:
213 {
214 MI_StringAField* f = (MI_StringAField*)field;
215
216 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
217
218 if (f->exists)
219 {
220 MI_RETURN_ERR(Buf_PackStrA(buf,
221 (const MI_Char**)f->value.data, f->value.size));
222 }
223 break;
224 }
225 case MI_INSTANCEA:
226 case MI_REFERENCEA:
227 {
228 MI_InstanceAField* f = ((MI_InstanceAField*)field);
229
230 MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
231
232 mike 1.1 if (f->exists)
233 {
234 MI_Uint32 index;
235 MI_RETURN_ERR(Buf_PackU32(buf, f->value.size));
236
237 for ( index = 0; index < f->value.size; index++ )
238 {
239 MI_RETURN_ERR(Instance_Pack(f->value.data[index],
240 type == MI_REFERENCEA, NULL, NULL, buf));
241 }
242 }
243 break;
244 }
245 default:
246 break;
247 }
248
249 MI_RETURN(MI_RESULT_OK);
250 }
251
252 static MI_Result _UnpackField(
253 mike 1.1 Buf* buf,
254 MI_Value* value,
255 MI_Boolean* exists,
256 MI_Type type,
257 Batch* batch,
258 MI_Boolean copy)
259 {
260 /* Get exists flag */
261 MI_RETURN_ERR(Buf_UnpackU8(buf, exists));
262
263 if (!*exists)
264 {
265 memset(value, 0, sizeof(MI_Value));
266 MI_RETURN(MI_RESULT_OK);
267 }
268
269 /* Get value */
270 switch (type)
271 {
272 case MI_UINT8:
273 case MI_SINT8:
274 mike 1.1 case MI_BOOLEAN:
275 {
276 MI_RETURN_ERR(Buf_UnpackU8(buf, &value->uint8));
277 break;
278 }
279 case MI_UINT16:
280 case MI_SINT16:
281 case MI_CHAR16:
282 {
283 MI_RETURN_ERR(Buf_UnpackU16(buf, &value->uint16));
284 break;
285 }
286 case MI_UINT32:
287 case MI_SINT32:
288 case MI_REAL32:
289 {
290 MI_RETURN_ERR(Buf_UnpackU32(buf, &value->uint32));
291 break;
292 }
293 case MI_UINT64:
294 case MI_SINT64:
295 mike 1.1 case MI_REAL64:
296 {
297 MI_RETURN_ERR(Buf_UnpackU64(buf, &value->uint64));
298 break;
299 }
300 case MI_DATETIME:
301 {
302 MI_RETURN_ERR(Buf_UnpackDT(buf, &value->datetime));
303 break;
304 }
305 case MI_STRING:
306 {
307 MI_RETURN_ERR(Buf_UnpackStr(
308 buf, (const MI_Char**)&value->string));
309
310 break;
311 }
312 case MI_REFERENCE:
313 case MI_INSTANCE:
314 {
315 MI_RETURN(Instance_Unpack((MI_Instance**)&value->instance, buf, batch, copy));
316 mike 1.1 break;
317 }
318 case MI_BOOLEANA:
319 case MI_UINT8A:
320 case MI_SINT8A:
321 {
322 MI_RETURN_ERR(Buf_UnpackU8A(buf,
323 (const MI_Uint8**)&value->uint8a.data, &value->uint8a.size));
324 break;
325 }
326 case MI_UINT16A:
327 case MI_SINT16A:
328 case MI_CHAR16A:
329 {
330 MI_RETURN_ERR(Buf_UnpackU16A(buf,
331 (const MI_Uint16**)&value->uint16a.data, &value->uint16a.size));
332 break;
333 }
334 case MI_UINT32A:
335 case MI_SINT32A:
336 case MI_REAL32A:
337 mike 1.1 {
338 MI_RETURN_ERR(Buf_UnpackU32A(buf,
339 (const MI_Uint32**)&value->uint32a.data, &value->uint32a.size));
340 break;
341 }
342 case MI_UINT64A:
343 case MI_SINT64A:
344 case MI_REAL64A:
345 {
346 MI_RETURN_ERR(Buf_UnpackU64A(buf,
347 (const MI_Uint64**)&value->uint64a.data, &value->uint64a.size));
348 break;
349 }
350 case MI_DATETIMEA:
351 {
352 MI_RETURN_ERR(Buf_UnpackDTA(buf,
353 (const MI_Datetime**)&value->datetimea.data,
354 &value->datetimea.size));
355 }
356 case MI_STRINGA:
357 {
358 mike 1.1 MI_RETURN_ERR(Buf_UnpackStrA(buf,
359 (const MI_Char***)&value->stringa.data, &value->stringa.size));
360 break;
361 }
362 case MI_INSTANCEA:
363 case MI_REFERENCEA:
364 {
365 /* Unpack the size of the array */
366 MI_RETURN_ERR(Buf_UnpackU32(buf, &value->instancea.size));
367
368 if (!value->instancea.size)
369 {
370 value->instancea.data = 0;
371 }
372 else
373 {
374 MI_Uint32 index;
375
376 value->instancea.data = (MI_Instance**)_Alloc(batch,
377 sizeof(MI_Instance*) * value->instancea.size);
378
379 mike 1.1 index = 0;
380 if (!value->instancea.data)
381 {
382 MI_RETURN(MI_RESULT_FAILED);
383 }
384
385 for ( index = 0; index < value->instancea.size; index++ )
386 {
387 MI_RETURN_ERR(Instance_Unpack(
388 &value->instancea.data[index], buf, batch, copy));
389 }
390 }
391 break;
392 }
393 }
394
395 MI_RETURN(MI_RESULT_OK);
396 }
397
398 MI_Result Instance_Pack(
399 const MI_Instance* self_,
400 mike 1.1 MI_Boolean keysOnly,
401 MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
402 void* filterPropertyData,
403 Buf* buf)
404 {
405 Instance* self = _SelfOf(self_);
406 MI_ClassDecl* cd = (MI_ClassDecl*)self->classDecl;
407 MI_Uint32 i;
408
409 /* Check for null arguments */
410 if (!self || !buf)
411 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
412
413 /* Pack magic number */
414 MI_RETURN_ERR(Buf_PackU32(buf, INSTANCE_MAGIC));
415
416 /* Pack flags */
417 MI_RETURN_ERR(Buf_PackU32(buf, cd->flags));
418
419 /* Pack the classname */
420 MI_RETURN_ERR(Buf_PackStr(buf, cd->name));
421 mike 1.1
422 /* namespace */
423 MI_RETURN_ERR(Buf_PackStr(buf, self->nameSpace));
424
425 /* Pack the properties */
426 if (keysOnly)
427 {
428 /* adjust number of properties based on Keys number */
429 MI_Uint32 keysNum = 0;
430
431 for (i = 0; i < cd->numProperties; i++)
432 {
433 const MI_PropertyDecl* pd = cd->properties[i];
434
435 if (pd->flags & MI_FLAG_KEY)
436 keysNum++;
437 }
438
439 MI_RETURN_ERR(Buf_PackU32(buf, keysNum));
440 }
441 else if (filterProperty)
442 mike 1.1 {
443 /* Pack the number of unfiltered properties */
444 MI_Uint32 n = 0;
445
446 for (i = 0; i < cd->numProperties; i++)
447 {
448 const MI_PropertyDecl* pd = cd->properties[i];
449
450 if ((*filterProperty)(pd->name, filterPropertyData))
451 continue;
452
453 n++;
454 }
455
456 MI_RETURN_ERR(Buf_PackU32(buf, n));
457 }
458 else
459 {
460 MI_RETURN_ERR(Buf_PackU32(buf, cd->numProperties));
461 }
462
463 mike 1.1 for (i = 0; i < cd->numProperties; i++)
464 {
465 const MI_PropertyDecl* pd = cd->properties[i];
466 const void* value = (char*)self + pd->offset;
467
468 /* Skip non-key properties (for references) */
469 if (keysOnly && (pd->flags & MI_FLAG_KEY) == 0)
470 continue;
471
472 /* Skip filtered properties */
473 if (filterProperty &&
474 (*filterProperty)(pd->name, filterPropertyData))
475 {
476 continue;
477 }
478
479 /* Pack the flags */
480 MI_RETURN_ERR(Buf_PackU32(buf, pd->flags));
481
482 /* Pack the propety name */
483 MI_RETURN_ERR(Buf_PackStr(buf, pd->name));
484 mike 1.1
485 /* Pack the propety type */
486 MI_RETURN_ERR(Buf_PackU32(buf, pd->type));
487
488 /* Pack the value */
489 MI_RETURN_ERR(_PackField(buf, value, (MI_Type)pd->type));
490 }
491
492 /* Pack ending magic number */
493 MI_RETURN_ERR(Buf_PackU32(buf, _END_MAGIC));
494
495 MI_RETURN(MI_RESULT_OK);
496 }
497
498 MI_Result Instance_Unpack(
499 MI_Instance** selfOut,
500 Buf* buf,
501 Batch* batch,
502 MI_Boolean copy)
503 {
504 MI_Uint32 magic;
505 mike 1.1 MI_Uint32 flags;
506 const MI_Char* className;
507 const MI_Char* nameSpace = 0;
508 MI_Instance* self;
509
510 /* Check parameters */
511 if (!selfOut || !buf)
512 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
513
514 /* Clear output parameter */
515 *selfOut = NULL;
516
517 /* Unpack magic number */
518 MI_RETURN_ERR(Buf_UnpackU32(buf, &magic));
519
520 if (INSTANCE_MAGIC != magic)
521 MI_RETURN(MI_RESULT_FAILED);
522
523 /* Unpack flags */
524 MI_RETURN_ERR(Buf_UnpackU32(buf, &flags));
525
526 mike 1.1 /* Unpack the class name */
527 MI_RETURN_ERR(Buf_UnpackStr(buf, &className));
528
529 /* Unpack the namespace */
530 MI_RETURN_ERR(Buf_UnpackStr(buf, &nameSpace));
531
532 /* Unpack properties */
533 {
534 MI_Uint32 numProperties;
535 MI_Uint32 i;
536
537 MI_RETURN_ERR(Buf_UnpackU32(buf, &numProperties));
538
539 /* ATTN-B: prevent copying of className and superClass strings */
540 /* Create dynamic instance */
541 MI_RETURN_ERR(Instance_NewDynamic(&self, className, flags, batch));
542
543 MI_RETURN_ERR(MI_Instance_SetNameSpace(self, nameSpace));
544
545 for (i = 0; i < numProperties; i++)
546 {
547 mike 1.1 const MI_Char* name;
548 MI_Uint32 type, prop_flags;
549 MI_Value value;
550 const MI_Value* valuePtr;
551 MI_Boolean exists;
552
553 /* ATTN-B: prevent copying of name by Instance_Add */
554 /* Unpack the propety type */
555 MI_RETURN_ERR(Buf_UnpackU32(buf, &prop_flags));
556
557 /* Unpack the propety name */
558 MI_RETURN_ERR(Buf_UnpackStr(buf, &name));
559
560 /* Unpack the propety type */
561 MI_RETURN_ERR(Buf_UnpackU32(buf, &type));
562
563 /* Unpack the value */
564 MI_RETURN_ERR(_UnpackField(buf, &value, &exists, (MI_Type)type,
565 batch, copy));
566
567 /* Set valuePtr */
568 mike 1.1 if (exists)
569 valuePtr = &value;
570 else
571 valuePtr = NULL;
572
573 /* ATTN-A: Handle prop_flags and className parameters */
574 /* Add the property to the instance */
575
576 if (!copy)
577 prop_flags |= MI_FLAG_BORROW;
578
579 MI_RETURN_ERR(MI_Instance_AddElement(self, name, valuePtr,
580 (MI_Type)type, prop_flags));
581 }
582 }
583
584 /* Check the ending magic number */
585 {
586 MI_Uint32 endMagic;
587 MI_RETURN_ERR(Buf_UnpackU32(buf, &endMagic));
588
589 mike 1.1 if (endMagic != _END_MAGIC)
590 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
591 }
592
593 /* Set output parameter */
594 *selfOut = self;
595
596 /* ATTN-A: if batch is non-null, then attach buffer to batch */
597 MI_RETURN(MI_RESULT_OK);
598 }
599
600 MI_Result InstanceToBatch(
601 const MI_Instance* instance,
602 MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
603 void* filterPropertyData,
604 Batch* batch,
605 void** ptrOut,
606 MI_Uint32* sizeOut)
607 {
608 Buf buf;
609 MI_Result r;
610 mike 1.1 Page* page;
611
612 r = Buf_Init(&buf, 16*1024);
613
614 if (MI_RESULT_OK != r)
615 return r;
616
617 r = Instance_Pack(
618 instance, MI_FALSE, filterProperty, filterPropertyData, &buf);
619
620 if (MI_RESULT_OK != r)
621 {
622 Buf_Destroy(&buf);
623 return r;
624 }
625
626 page = Buf_StealPage(&buf);
627 page->u.s.size = buf.size;
628
629 Batch_AttachPage(batch, page);
630
631 mike 1.1 *ptrOut = page + 1;
632 *sizeOut = (MI_Uint32)page->u.s.size;
633 return MI_RESULT_OK;
634 }
|