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 <common.h>
26 #include "wsbuf.h"
27 #include <base/log.h>
28 #include <base/result.h>
29 #include <base/instance.h>
30 #include <base/strings.h>
31 #include <base/field.h>
32 #include <base/messages.h>
33 #include <base/helpers.h>
34 #include <base/time.h>
35 #include <base/io.h>
36 #include <base/base64.h>
37
38 #if defined(WSBUF_DISABLE_INLINING)
39 # include "wsbufinline.h"
40 #endif
41
42 #define T MI_T
43 mike 1.1
44 #if 0
45 #define ENABLE_TRACING
46 #endif
47
48 #ifdef ENABLE_TRACING
49 #define PRINTF(a) printf a
50 #else
51 #define PRINTF(a)
52 #endif
53
54 #define XML_CR MI_T("\n")
55
56 /*
57 **==============================================================================
58 **
59 ** Local datatypes:
60 **
61 **==============================================================================
62 */
63 typedef struct _BUF_FaultItem
64 mike 1.1 {
65 const MI_Char* action;
66 MI_Uint32 actionSize;
67 const char* code; /* sender/receiver */
68 const char* subCode; /* wsa:XXX */
69 const char* defaultTest;
70 }
71 BUF_FaultItem;
72
73 typedef struct _BUF_CIMErrorItem
74 {
75 WSBUF_FAULT_CODE faultCode;
76 const MI_Char* description;
77 }
78 BUF_CIMErrorItem;
79
80 /*
81 **==============================================================================
82 **
83 ** Forward declarations:
84 **
85 mike 1.1 **==============================================================================
86 */
87 static MI_Result _PackInstance(
88 WSBuf* buf,
89 const MI_Instance* instance,
90 MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
91 void* filterPropertyData,
92 const MI_ClassDecl* castToClassDecl,
93 MI_Uint32 flags,
94 MI_Boolean embedded);
95
96 static MI_Result _PackEPR(
97 WSBuf* buf,
98 const MI_Instance* instance);
99
100 /*
101 **==============================================================================
102 **
103 ** Static data:
104 **
105 **==============================================================================
106 mike 1.1 */
107
108 static const BUF_FaultItem s_faults[] = {
109 /* WSBUF_FAULT_INTERNAL_ERROR */
110 {
111 LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
112 "SOAP-ENV:Receiver",
113 "wsman:InternalError",
114 "The service cannot comply with the request due to internal processing errors."
115 },
116 /* WSBUF_FAULT_NOT_SUPPORTED */
117 {
118 LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
119 "SOAP-ENV:Sender",
120 "wsman:UnsupportedFeature",
121 "not supported"
122 },
123 /* WSBUF_FAULT_NOT_UNDERSTOOD */
124 {
125 LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/08/addressing/fault")),
126 "SOAP-ENV:MustUnderstand",
127 mike 1.1 0,
128 "Header not understood"
129 },
130 /* WSBUF_FAULT_DESTINATION_UNREACHABLE */
131 {
132 LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/08/addressing/fault")),
133 "SOAP-ENV:Sender",
134 "wsa:DestinationUnreachable",
135 "No route can be determined to reach the destination role defined by the Addressing To header."
136 },
137 /* WSBUF_FAULT_ACCESS_DENIED */
138 {
139 LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
140 "SOAP-ENV:Sender",
141 "wsman:AccessDenied",
142 "The sender was not authorized to access the resource."
143 },
144 /* WSBUF_FAULT_ENCODING_LIMIT */
145 {
146 LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
147 "SOAP-ENV:Sender",
148 mike 1.1 "wsman:EncodingLimit",
149 "An internal encoding limit was exceeded in a request or would be violated if the message were processed."
150 }
151 };
152
153 static const BUF_CIMErrorItem s_cimerrors[] = {
154 /* MI_RESULT_OK = 0, */
155 {
156 0,
157 0
158 },
159 /* MI_RESULT_FAILED = 1, */
160 {
161 WSBUF_FAULT_INTERNAL_ERROR,
162 MI_T("CIM ERROR:FAILED: A general error occurred, not covered by a more specific error code.")
163 },
164
165 /* MI_RESULT_ACCESS_DENIED = 2, */
166 {
167 WSBUF_FAULT_ACCESS_DENIED,
168 MI_T("CIM ERROR:ACCESS_DENIED: Access to a CIM resource is not available to the client.")
169 mike 1.1 },
170
171 /* MI_RESULT_INVALID_NAMESPACE = 3, */
172 {
173 WSBUF_FAULT_DESTINATION_UNREACHABLE,
174 MI_T("CIM ERROR:INVALID_NAMESPACE: The target namespace does not exist.")
175 },
176
177 /* MI_RESULT_INVALID_PARAMETER = 4,*/
178 {
179 WSBUF_FAULT_INTERNAL_ERROR,
180 MI_T("CIM ERROR:INVALID_PARAMETER: One or more parameter values passed to the method are not valid.")
181 },
182
183 /* MI_RESULT_INVALID_CLASS = 5, */
184 {
185 WSBUF_FAULT_DESTINATION_UNREACHABLE,
186 MI_T("CIM ERROR:INVALID_CLASS: The specified class does not exist.")
187 },
188
189 /* MI_RESULT_NOT_FOUND = 6,*/
190 mike 1.1 {
191 WSBUF_FAULT_DESTINATION_UNREACHABLE,
192 MI_T("CIM ERROR:NOT_FOUND: The requested object cannot be found.")
193 },
194
195 /* MI_RESULT_NOT_SUPPORTED = 7, */
196 {
197 WSBUF_FAULT_NOT_SUPPORTED,
198 MI_T("CIM ERROR:NOT_SUPPORTED: The requested operation is not supported.")
199 }
200
201 #if 0
202 /* The operation cannot be invoked because the class has subclasses. */
203 MI_RESULT_CLASS_HAS_CHILDREN = 8,
204
205 /* The operation cannot be invoked because the class has instances. */
206 MI_RESULT_CLASS_HAS_INSTANCES = 9,
207
208 /* The operation cannot be invoked because the superclass does not exist. */
209 MI_RESULT_INVALID_SUPERCLASS = 10,
210
211 mike 1.1 /* The operation cannot be invoked because an object already exists. */
212 MI_RESULT_ALREADY_EXISTS = 11,
213
214 /* The specified property does not exist. */
215 MI_RESULT_NO_SUCH_PROPERTY = 12,
216
217 /* The value supplied is not compatible with the type. */
218 MI_RESULT_TYPE_MISMATCH = 13,
219
220 /* The query language is not recognized or supported. */
221 MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED = 14,
222
223 /* The query is not valid for the specified query language. */
224 MI_RESULT_INVALID_QUERY = 15,
225
226 /* The extrinsic method cannot be invoked. */
227 MI_RESULT_METHOD_NOT_AVAILABLE = 16,
228
229 /* The specified extrinsic method does not exist. */
230 MI_RESULT_METHOD_NOT_FOUND = 17,
231
232 mike 1.1 /* The specified namespace is not empty. */
233 MI_RESULT_NAMESPACE_NOT_EMPTY = 20,
234
235 /* The enumeration identified by the specified context is invalid. */
236 MI_RESULT_INVALID_ENUMERATION_CONTEXT = 21,
237
238 /* The specified operation timeout is not supported by the CIM Server. */
239 MI_RESULT_INVALID_OPERATION_TIMEOUT = 22,
240
241 /* The Pull operation has been abandoned. */
242 MI_RESULT_PULL_HAS_BEEN_ABANDONED = 23,
243
244 /* The attempt to abandon a concurrent Pull operation failed. */
245 MI_RESULT_PULL_CANNOT_BE_ABANDONED = 24,
246
247 /* Using a filter in the enumeration is not supported by the CIM server. */
248 MI_RESULT_FILTERED_ENUMERATION_NOT_SUPPORTED = 25,
249
250 /* The CIM server does not support continuation on error. */
251 MI_RESULT_CONTINUATION_ON_ERROR_NOT_SUPPORTED = 26,
252
253 mike 1.1 /* The operation failed because server limits were exceeded. */
254 MI_RESULT_SERVER_LIMITS_EXCEEDED = 27,
255
256 /* The CIM server is shutting down and cannot process the operation. */
257 MI_RESULT_SERVER_IS_SHUTTING_DOWN = 28
258 #endif
259 };
260
261 /* Encodings for special XML characters */
262 static const char* s_specialCharEncodings[128] =
263 {
264 "\004�",
265 "\004",
266 "\004",
267 "\004",
268 "\004",
269 "\004",
270 "\004",
271 "\004",
272 "\004",
273 "\004	",
274 mike 1.1 "\005 ",
275 "\005",
276 "\005",
277 "\005 ",
278 "\005",
279 "\005",
280 "\005",
281 "\005",
282 "\005",
283 "\005",
284 "\005",
285 "\005",
286 "\005",
287 "\005",
288 "\005",
289 "\005",
290 "\005",
291 "\005",
292 "\005",
293 "\005",
294 "\005",
295 mike 1.1 "\005",
296 "\001 ",
297 "\001!",
298 "\006"",
299 "\001#",
300 "\001$",
301 "\001%",
302 "\005&",
303 "\006'",
304 "\001(",
305 "\001)",
306 "\001*",
307 "\001+",
308 "\001,",
309 "\001-",
310 "\001.",
311 "\001/",
312 "\0010",
313 "\0011",
314 "\0012",
315 "\0013",
316 mike 1.1 "\0014",
317 "\0015",
318 "\0016",
319 "\0017",
320 "\0018",
321 "\0019",
322 "\001:",
323 "\001;",
324 "\004<",
325 "\001=",
326 "\004>",
327 "\001?",
328 "\001@",
329 "\001A",
330 "\001B",
331 "\001C",
332 "\001D",
333 "\001E",
334 "\001F",
335 "\001G",
336 "\001H",
337 mike 1.1 "\001I",
338 "\001J",
339 "\001K",
340 "\001L",
341 "\001M",
342 "\001N",
343 "\001O",
344 "\001P",
345 "\001Q",
346 "\001R",
347 "\001S",
348 "\001T",
349 "\001U",
350 "\001V",
351 "\001W",
352 "\001X",
353 "\001Y",
354 "\001Z",
355 "\001[",
356 "\001\\",
357 "\001]",
358 mike 1.1 "\001^",
359 "\001_",
360 "\001`",
361 "\001a",
362 "\001b",
363 "\001c",
364 "\001d",
365 "\001e",
366 "\001f",
367 "\001g",
368 "\001h",
369 "\001i",
370 "\001j",
371 "\001k",
372 "\001l",
373 "\001m",
374 "\001n",
375 "\001o",
376 "\001p",
377 "\001q",
378 "\001r",
379 mike 1.1 "\001s",
380 "\001t",
381 "\001u",
382 "\001v",
383 "\001w",
384 "\001x",
385 "\001y",
386 "\001z",
387 "\001{",
388 "\001|",
389 "\001}",
390 "\001~",
391 "\006",
392 };
393
394 /* This table idnetifies special XML characters. */
395 static const char s_specialChars[256] =
396 {
397 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
398 0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,
399 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
400 mike 1.1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
401 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
402 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
403 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
404 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
405 };
406
407 /*
408 **==============================================================================
409 **
410 ** Local definitions:
411 **
412 **==============================================================================
413 */
414 MI_INLINE MI_Boolean _Field_GetExists(
415 const void* field,
416 MI_Type type)
417 {
418 return Field_GetExists((const Field*)field, type);
419 }
420
421 mike 1.1 static MI_Result _ReallocPage(
422 WSBuf* buf,
423 MI_Uint32 newSize)
424 {
425 Page* new_page;
426
427 /* round up to next 1k */
428 #define WSMAN_BUF_CAPACITY 1024
429 newSize = ((newSize + WSMAN_BUF_CAPACITY) / WSMAN_BUF_CAPACITY) * WSMAN_BUF_CAPACITY;
430 new_page = (Page*)realloc(buf->page, sizeof(Page) + newSize);
431
432 if (!new_page)
433 return MI_RESULT_FAILED;
434
435 buf->page = new_page;
436 buf->page->u.s.size = newSize;
437 return MI_RESULT_OK;
438 }
439
440 #if 0
441 #if (MI_CHAR_TYPE == 1)
442 mike 1.1 #define FIRST_HIGH_SURROGATE 0xD800
443 #define LAST_HIGH_SURROGATE 0xDBFF
444
445 static void _UTF16toUTF8(
446 MI_Char16 c,
447 char* s)
448 {
449 static const MI_Uint8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
450 MI_Uint8* tgt = (MI_Uint8*)s;
451 MI_Uint32 numberOfBytes;
452
453 /* not a valid single char */
454 if (c >= FIRST_HIGH_SURROGATE
455 && c <= LAST_HIGH_SURROGATE)
456 {
457 s[0] = '?';
458 s[1] = 0;
459 return;
460 }
461
462 if (c < 0x80)
463 mike 1.1 {
464 numberOfBytes = 1;
465 }
466 else if (c < 0x800)
467 {
468 numberOfBytes = 2;
469 }
470 else
471 {
472 numberOfBytes = 3;
473 }
474
475 tgt += numberOfBytes;
476
477 switch (numberOfBytes)
478 {
479 case 3:
480 *--tgt = (MI_Uint8)((c | 0x80) & 0xBF);
481 c >>= 6;
482 case 2:
483 *--tgt = (MI_Uint8)((c | 0x80) & 0xBF);
484 mike 1.1 c >>= 6;
485 case 1:
486 *--tgt = (MI_Uint8)(c | firstByteMark[numberOfBytes]);
487 }
488 }
489 #endif
490 #endif
491
492 /*
493 **==============================================================================
494 **
495 ** Public API:
496 **
497 **==============================================================================
498 */
499 MI_Result WSBuf_Init(
500 WSBuf* buf,
501 MI_Uint32 initialSize)
502 {
503 buf->page = (Page*)malloc(sizeof(Page) + initialSize);
504 buf->position = 0;
505 mike 1.1
506 if (!buf->page)
507 {
508 return MI_RESULT_FAILED;
509 }
510
511 buf->page->u.s.size = initialSize;
512 buf->page->u.s.next = 0;
513 /* Put empty string inside */
514 ((MI_Char*)(buf->page +1))[0] = 0;
515 return MI_RESULT_OK;
516 }
517
518 MI_Result WSBuf_Destroy(
519 WSBuf* buf)
520 {
521 if (buf->page)
522 free(buf->page);
523
524 return MI_RESULT_OK;
525 }
526 mike 1.1
527 #if (MI_CHAR_TYPE == 1)
528 Page* WSBuf_StealPage(
529 WSBuf* buf)
530 {
531 Page* res = buf->page;
532
533 if (!res)
534 return 0;
535
536 buf->page = 0;
537 res->u.s.size = buf->position;
538 buf->position = 0;
539
540 return res;
541 }
542 #else
543 Page* WSBuf_StealPage(
544 WSBuf* buf)
545 {
546
547 mike 1.1 if (!buf->page)
548 return 0;
549
550 /* convert wchar_t to utf-8
551 unfortunately, Windows does not support wchat -> utf8 conversion in crt */
552
553 {
554 Page* res;
555 const MI_Char* text = ((MI_Char*)(buf->page +1));
556 int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, 0, NULL);
557
558 if (size == 0)
559 goto failed;
560
561 res = (Page*)malloc(sizeof(Page) + size);
562
563 if (!res)
564 goto failed;
565
566 if (WideCharToMultiByte(CP_UTF8, 0, text, -1, (char*)(res + 1), size, 0, NULL) == 0)
567 {
568 mike 1.1 free(res);
569 goto failed;
570 }
571
572 res->u.s.size = size - 1;
573 res->u.s.next = 0;
574
575 free(buf->page);
576 buf->page = 0;
577 buf->position = 0;
578 return res;
579 }
580
581 failed:
582 free(buf->page);
583 buf->page = 0;
584 return 0;
585 }
586 #endif
587
588 MI_Result WSBuf_AddUint32(
589 mike 1.1 WSBuf* buf,
590 MI_Uint32 x)
591 {
592 MI_Char tmp[12];
593 size_t size;
594 const MI_Char* s = Uint32ToZStr(tmp, x, &size);
595 return WSBuf_AddLit(buf, s, (MI_Uint32)size);
596 }
597
598 MI_Result __WSBuf_AddLit(
599 WSBuf* buf,
600 const MI_Char* str,
601 MI_Uint32 size)
602 {
603 MI_Uint32 n = (size + 1) * sizeof(MI_Char);
604
605 /* Extend buffer (WSBuf_AddLit determined it was too small) */
606 if (_ReallocPage(buf, n + buf->position) != MI_RESULT_OK)
607 return MI_RESULT_FAILED;
608
609 /* Add string */
610 mike 1.1 {
611 char* data = ((char*)(buf->page+1)) + buf->position;
612 memcpy( data, str, n - sizeof(MI_Char));
613 ((MI_Char*)data)[size] = 0;
614
615 buf->position += n - sizeof(MI_Char);
616 }
617
618 return MI_RESULT_OK;
619 }
620
621 /* Add string with proper xml encoding */
622 MI_Result WSBuf_AddString(
623 WSBuf* buf,
624 const MI_Char* str)
625 {
626 #if (MI_CHAR_TYPE == 1)
627 /* Process leading non-special characters in the hope that little will
628 * be left over to be encoded the expensive way below this block.
629 */
630 {
631 mike 1.1 const unsigned char* start = (const unsigned char*)str;
632 const unsigned char* p = start;
633
634 while (!s_specialChars[*p])
635 p++;
636
637 if (p != start)
638 {
639 if (WSBuf_AddLit(buf, (const char*)start, (MI_Uint32)(p - start)))
640 return MI_RESULT_FAILED;
641
642 str = (const char*)p;
643 }
644
645 if (!*str)
646 return MI_RESULT_OK;
647 }
648 #endif
649
650 /* Now encode what remains (starting with first special char hit above) */
651 {
652 mike 1.1 /*MI_Uint32 size = (MI_Uint32)((MI_Strlen(str) + 1)*sizeof(MI_Char));*/
653 MI_Char* pos = (MI_Char*)(((char*)(buf->page +1)) + buf->position);
654 MI_Char* end = (MI_Char*)(((char*)(buf->page +1)) + buf->page->u.s.size);
655
656 /* Add reamingin characters (next character is special) */
657 while (*str)
658 {
659 const MI_Char* item;
660 size_t size_chars;
661 MI_Uint32 c = (MI_Uint32)(MI_Sint16)*str;
662
663 /* if c is ascii ?*/
664 if (c < 128)
665 {
666 /* First byte is the length */
667 item = s_specialCharEncodings[c] + 1;
668 size_chars = s_specialCharEncodings[c][0];
669 }
670 else
671 {
672 item = str;
673 mike 1.1 size_chars = 1;
674 }
675
676 /* Extend buffer if needed */
677 if ( (size_t)(end - pos) <= (size_chars + 1))
678 {
679 size_t current_pos =
680 (pos - ((MI_Char*)(buf->page +1))) * sizeof(MI_Char);
681
682 if (_ReallocPage(buf, (MI_Uint32)(buf->page->u.s.size + size_chars * sizeof(MI_Char))) != MI_RESULT_OK)
683 return MI_RESULT_FAILED;
684
685 pos = (MI_Char*)(((char*)(buf->page +1)) + current_pos);
686 end = (MI_Char*)(((char*)(buf->page +1)) + buf->page->u.s.size);
687 }
688
689 if (1 == size_chars)
690 *pos = *item;
691 else
692 memcpy( pos, item, size_chars * sizeof(MI_Char));
693
694 mike 1.1 pos += size_chars;
695 str++;
696 }
697
698 buf->position = (MI_Uint32)((pos - ((MI_Char*)(buf->page +1))) * sizeof(MI_Char));
699
700 /* put \0 at the end */
701 ((MI_Char*)(((char*)(buf->page +1)) + buf->position))[0] = 0;
702
703 return MI_RESULT_OK;
704 }
705 }
706
707 #if (MI_CHAR_TYPE != 1)
708 MI_Result WSBuf_AddCharStringNoEncoding(
709 WSBuf* buf,
710 const char* str)
711 {
712 return WSBuf_AddCharLit(buf, str, (MI_Uint32)strlen(str));
713 }
714
715 mike 1.1 MI_Result WSBuf_AddCharLit(
716 WSBuf* buf,
717 const char* str,
718 MI_Uint32 size_)
719 {
720 MI_Uint32 size = (MI_Uint32)((size_ + 1)*sizeof(MI_Char));
721
722 /* Extend buffer if needed */
723 if (size + buf->position > buf->page->u.s.size &&
724 _ReallocPage(buf, size + buf->position) != MI_RESULT_OK)
725 return MI_RESULT_FAILED;
726
727 {
728 MI_Char* data = (MI_Char*)(((char*)(buf->page +1)) + buf->position);
729 MI_Uint32 i;
730
731 for (i = 0; i < size_; i++)
732 {
733 *data++ = *str++;
734 }
735 buf->position += size - sizeof(MI_Char);
736 mike 1.1 }
737
738 return MI_RESULT_OK;
739 }
740
741 #endif
742
743 /* Callback to tag writer:
744 allows to write properties for both values/EPRs with the same routine */
745 typedef MI_Result (*PropertyTagWriter)(
746 WSBuf* buf,
747 const MI_Char* name,
748 MI_Boolean start);
749
750 INLINE MI_Result PropertyTagWriter_PropStart(
751 WSBuf* buf,
752 const MI_Char* name)
753 {
754 MI_Uint32 n = (MI_Uint32)Zlen(name);
755
756 if (MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
757 mike 1.1 MI_RESULT_OK != WSBuf_AddLit(buf, name, n) ||
758 MI_RESULT_OK != WSBuf_AddLit1(buf,'>'))
759 {
760 return MI_RESULT_FAILED;
761 }
762
763 return MI_RESULT_OK;
764 }
765
766 INLINE MI_Result PropertyTagWriter_PropEnd(
767 WSBuf* buf,
768 const MI_Char* name)
769 {
770 MI_Uint32 n = (MI_Uint32)Zlen(name);
771
772 if (MI_RESULT_OK != WSBuf_AddLit4(buf, '<', '/', 'p', ':') ||
773 MI_RESULT_OK != WSBuf_AddLit(buf, name, n) ||
774 MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
775 {
776 return MI_RESULT_FAILED;
777 }
778 mike 1.1
779 return MI_RESULT_OK;
780 }
781
782 static MI_Result PropertyTagWriter_Prop(
783 WSBuf* buf,
784 const MI_Char* name,
785 MI_Boolean start)
786 {
787 if (start)
788 return PropertyTagWriter_PropStart(buf, name);
789 else
790 return PropertyTagWriter_PropEnd(buf, name);
791 }
792
793 static MI_Result PropertyTagWriter_EPR(
794 WSBuf* buf,
795 const MI_Char* name,
796 MI_Boolean start)
797 {
798 if (start)
799 mike 1.1 {
800 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsman:Selector Name=\""))) ||
801 MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,name) ||
802 MI_RESULT_OK != WSBuf_AddLit2(buf, '"', '>')
803 )
804 return MI_RESULT_FAILED;
805 }
806 else
807 {
808 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:Selector>") XML_CR))
809 )
810 return MI_RESULT_FAILED;
811 }
812
813 return MI_RESULT_OK;
814 }
815
816 static MI_Result _PackFieldNil(
817 WSBuf* buf,
818 const MI_Char* name)
819 {
820 mike 1.1 if ( MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
821 MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,name) ||
822 MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xsi:nil=\"true\"/>") XML_CR)) )
823 return MI_RESULT_FAILED;
824
825 return MI_RESULT_OK;
826 }
827
828 static int _Base64Callback(
829 const char* data,
830 size_t size,
831 void* callbackData)
832 {
833 WSBuf* buf = callbackData;
834 return WSBuf_AddLit(buf, data, size) == MI_RESULT_OK ? 0 : -1;
835 }
836
837 static MI_Result _PackFieldOctetString(
838 WSBuf* buf,
839 const MI_Char* name,
840 const MI_Uint8* data,
841 mike 1.1 size_t size)
842 {
843 /* Validate first 4 bytes which contain the length then remove them */
844 {
845 size_t length = 0;
846
847 if (size < 4)
848 return MI_RESULT_FAILED;
849
850 length |= data[0] << 24;
851 length |= data[1] << 16;
852 length |= data[2] << 8;
853 length |= data[3];
854
855 if (length != size)
856 return MI_RESULT_FAILED;
857
858 data += 4;
859 size -= 4;
860 }
861
862 mike 1.1 if (WSBuf_AddLit3(buf, '<', 'p', ':') != MI_RESULT_OK)
863 return MI_RESULT_FAILED;
864
865 if (WSBuf_AddStringNoEncoding(buf, name) != MI_RESULT_OK)
866 return MI_RESULT_FAILED;
867
868 if (WSBuf_AddLit(buf,
869 LIT(MI_T(" xsi:type=\"cim:cimBase64Binary\">"))) != MI_RESULT_OK)
870 {
871 return MI_RESULT_FAILED;
872 }
873
874 if (Base64Enc(data, size, _Base64Callback, buf) != 0)
875 return MI_RESULT_FAILED;
876
877 if (PropertyTagWriter_PropEnd(buf, name) != MI_RESULT_OK)
878 return MI_RESULT_FAILED;
879
880 return MI_RESULT_OK;
881 }
882
883 mike 1.1 static MI_Result _PackFieldString(
884 WSBuf* buf,
885 PropertyTagWriter writer,
886 const MI_Char* name,
887 const MI_Char* value)
888 {
889 if ( MI_RESULT_OK != writer(buf,name,MI_TRUE) ||
890 MI_RESULT_OK != WSBuf_AddString(buf,value) ||
891 MI_RESULT_OK != writer(buf,name,MI_FALSE)
892 )
893 return MI_RESULT_FAILED;
894
895 return MI_RESULT_OK;
896 }
897
898 static MI_Result _PackFieldStringLit(
899 WSBuf* buf,
900 PropertyTagWriter writer,
901 const MI_Char* name,
902 const MI_Char* value,
903 MI_Uint32 valueSize)
904 mike 1.1 {
905 if ( MI_RESULT_OK != writer(buf,name,MI_TRUE) ||
906 MI_RESULT_OK != WSBuf_AddLit(buf,value,valueSize) ||
907 MI_RESULT_OK != writer(buf,name,MI_FALSE)
908 )
909 return MI_RESULT_FAILED;
910
911 return MI_RESULT_OK;
912 }
913
914 static MI_Result _PackFieldEmbeddedInstance(
915 WSBuf* buf,
916 const MI_Char* name,
917 const MI_Instance* value)
918 {
919 if ( MI_RESULT_OK != PropertyTagWriter_PropStart(buf,name) ||
920 MI_RESULT_OK != _PackInstance(buf,value,NULL,NULL,0,WSMAN_ObjectFlag,MI_TRUE) ||
921 MI_RESULT_OK != PropertyTagWriter_PropEnd(buf,name)
922 )
923 return MI_RESULT_FAILED;
924
925 mike 1.1 return MI_RESULT_OK;
926 }
927
928 static MI_Result _PackFieldRef(
929 WSBuf* buf,
930 const MI_Char* name,
931 const MI_Instance* value)
932 {
933 if ( MI_RESULT_OK != PropertyTagWriter_PropStart(buf,name) ||
934 MI_RESULT_OK != _PackEPR(buf,value) ||
935 MI_RESULT_OK != PropertyTagWriter_PropEnd(buf,name)
936 )
937 return MI_RESULT_FAILED;
938
939 return MI_RESULT_OK;
940 }
941
942 static MI_Result _PackFieldUint32(
943 WSBuf* buf,
944 PropertyTagWriter writer,
945 const MI_Char* name,
946 mike 1.1 MI_Uint32 value)
947 {
948 MI_Char tmp[11];
949 size_t size;
950 const MI_Char* str = Uint32ToZStr(tmp, value, &size);
951 return _PackFieldStringLit(buf,writer, name, str, (MI_Uint32)size);
952 }
953
954 static MI_Result _PackFieldUint64(
955 WSBuf* buf,
956 PropertyTagWriter writer,
957 const MI_Char* name,
958 MI_Uint64 value)
959 {
960 MI_Char tmp[21];
961 size_t size;
962 const MI_Char* str = Uint64ToZStr(tmp, value, &size);
963 return _PackFieldStringLit(buf, writer, name, str, (MI_Uint32)size);
964 }
965
966 static MI_Result _PackFieldSint32(
967 mike 1.1 WSBuf* buf,
968 PropertyTagWriter writer,
969 const MI_Char* name,
970 MI_Sint32 value)
971 {
972 MI_Char s[24];
973
974 MI_Sint32 size = Szprintf(s, MI_COUNT(s), MI_T("%d"), value);
975 return _PackFieldStringLit(buf,writer,name,s,size);
976 }
977
978 static MI_Result _PackFieldSint64(
979 WSBuf* buf,
980 PropertyTagWriter writer,
981 const MI_Char* name,
982 MI_Sint64 value)
983 {
984 MI_Char s[24];
985
986 MI_Sint32 size = Szprintf(s, MI_COUNT(s), SINT64_FMT_T, value);
987 return _PackFieldStringLit(buf,writer,name,s,size);
988 mike 1.1 }
989
990 static MI_Result _PackFieldReal64(
991 WSBuf* buf,
992 PropertyTagWriter writer,
993 const MI_Char* name,
994 MI_Real64 value)
995 {
996 MI_Char s[24];
997
998 MI_Sint32 size = Szprintf(s, MI_COUNT(s), MI_T("%g"), value);
999 return _PackFieldStringLit(buf,writer,name,s,size);
1000 }
1001
1002 static MI_Result _PackFieldDatetime(
1003 WSBuf* buf,
1004 PropertyTagWriter writer,
1005 const MI_Char* name,
1006 const MI_Datetime* p)
1007 {
1008 MI_Char tmp[64];
1009 mike 1.1 FormatWSManDatetime(p, tmp);
1010 return _PackFieldStringLit(buf, writer, name, tmp, (MI_Uint32)Zlen(tmp));
1011 }
1012
1013 static MI_Result _PackValue(
1014 WSBuf* buf,
1015 PropertyTagWriter writer,
1016 const MI_Char* name,
1017 const void* field,
1018 MI_Type type)
1019 {
1020 switch(type)
1021 {
1022 case MI_BOOLEAN:
1023 {
1024 MI_Boolean* f = (MI_Boolean*)field;
1025
1026 if (*f)
1027 return _PackFieldStringLit(buf,writer,name,LIT(MI_T("TRUE")));
1028 else
1029 return _PackFieldStringLit(buf,writer,name,LIT(MI_T("FALSE")));
1030 mike 1.1 }
1031 case MI_UINT8:
1032 {
1033 MI_Uint8* f = (MI_Uint8*)field;
1034
1035 return _PackFieldUint32(buf,writer,name,*f);
1036 }
1037 case MI_UINT16:
1038 {
1039 MI_Uint16* f = (MI_Uint16*)field;
1040
1041 return _PackFieldUint32(buf,writer,name,*f);
1042 }
1043 case MI_UINT32:
1044 {
1045 MI_Uint32* f = (MI_Uint32*)field;
1046
1047 return _PackFieldUint32(buf,writer,name,*f);
1048 }
1049 case MI_UINT64:
1050 {
1051 mike 1.1 MI_Uint64* f = (MI_Uint64*)field;
1052
1053 return _PackFieldUint64(buf,writer,name,*f);
1054 }
1055 case MI_SINT8:
1056 {
1057 MI_Sint8* f = (MI_Sint8*)field;
1058
1059 return _PackFieldSint32(buf,writer,name,*f);
1060 }
1061 case MI_SINT16:
1062 {
1063 MI_Sint16* f = (MI_Sint16*)field;
1064
1065 return _PackFieldSint32(buf,writer,name,*f);
1066 }
1067 case MI_SINT32:
1068 {
1069 MI_Sint32* f = (MI_Sint32*)field;
1070
1071 return _PackFieldSint32(buf,writer,name,*f);
1072 mike 1.1 }
1073 case MI_SINT64:
1074 {
1075 MI_Sint64* f = (MI_Sint64*)field;
1076
1077 return _PackFieldSint64(buf,writer,name,*f);
1078 }
1079 case MI_REAL32:
1080 {
1081 MI_Real32* f = (MI_Real32*)field;
1082
1083 return _PackFieldReal64(buf,writer,name,*f);
1084 }
1085 case MI_REAL64:
1086 {
1087 MI_Real64* f = (MI_Real64*)field;
1088
1089 return _PackFieldReal64(buf,writer,name,*f);
1090 }
1091 case MI_DATETIME:
1092 {
1093 mike 1.1 MI_Datetime* f = (MI_Datetime*)field;
1094
1095 return _PackFieldDatetime(buf,writer,name,&*f);
1096 }
1097 case MI_CHAR16:
1098 {
1099 MI_Char16* f = (MI_Char16*)field;
1100 #if 0
1101 #if (MI_CHAR_TYPE == 1)
1102 char s[6];
1103 memset(s,0,sizeof(s));
1104
1105 _UTF16toUTF8(*f,s);
1106 #else
1107 /* whcar_t -
1108 steal page will translate it */
1109 wchar_t s[2] = {0, 0};
1110
1111 s[0] = *f;
1112 #endif
1113
1114 mike 1.1 /* ATTN: convert it to utf8 and encode as a string */
1115 return _PackFieldString(buf,writer,name,s);
1116 #else
1117 return _PackFieldUint32(buf,writer,name,(MI_Uint32)*f);
1118 #endif
1119 }
1120 case MI_INSTANCE:
1121 {
1122 MI_Instance** f = (MI_Instance**)field;
1123
1124 return _PackFieldEmbeddedInstance(buf,name,*f);
1125 }
1126 case MI_REFERENCE:
1127 {
1128 MI_Instance** f = (MI_Instance**)field;
1129
1130 return _PackFieldRef(buf,name,*f);
1131 }
1132 case MI_STRING:
1133 {
1134 MI_String* f = (MI_String*)field;
1135 mike 1.1
1136 return _PackFieldString(buf,writer,name,*f);
1137 }
1138 default:
1139 break;
1140 }
1141
1142 return MI_RESULT_OK;
1143 }
1144
1145 static MI_Result _PackField(
1146 WSBuf* buf,
1147 PropertyTagWriter writer,
1148 const MI_Char* name,
1149 const void* field,
1150 MI_Type type,
1151 MI_Boolean isOctetString)
1152 {
1153 /* Check if value is null */
1154 if (!_Field_GetExists(field, type))
1155 return _PackFieldNil(buf, name);
1156 mike 1.1
1157 /* Check if type is array:
1158 Arrays are encoded the same way regular instances are
1159 with repeating instance as many times as many elements are in array */
1160 if (type & MI_ARRAY_BIT)
1161 {
1162 if (isOctetString && type == MI_UINT8A)
1163 {
1164 MI_Uint8AField* f = (MI_Uint8AField*)field;
1165 return _PackFieldOctetString(buf, name, f->value.data,
1166 f->value.size);
1167 }
1168
1169 /* ATTN: STRING OctetString not handled! */
1170
1171 {
1172 MI_ArrayField* f = (MI_ArrayField*)field;
1173 MI_Uint32 i;
1174 MI_Type stype = type & ~MI_ARRAY_BIT;
1175 char* currentValue = (char*)f->value.data;
1176
1177 mike 1.1 for (i = 0; i < f->value.size; i++)
1178 {
1179 if (_PackValue(
1180 buf,
1181 writer,
1182 name,
1183 currentValue,
1184 stype) != MI_RESULT_OK)
1185 {
1186 return MI_RESULT_FAILED;
1187 }
1188
1189 currentValue += Type_SizeOf(stype);
1190 }
1191
1192 return MI_RESULT_OK;
1193 }
1194 }
1195
1196 return _PackValue(buf, writer, name, field, type);
1197 }
1198 mike 1.1
1199 static MI_Result _PackEPR(
1200 WSBuf* buf,
1201 const MI_Instance* instance)
1202 {
1203 Instance* self = (Instance*)instance;
1204 const MI_ClassDecl* cd = self->classDecl;
1205 MI_Uint32 i;
1206
1207 /* Put EPR header */
1208 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>") XML_CR
1209 MI_T("<wsa:ReferenceParameters>") XML_CR
1210 MI_T("<wsman:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/") )) ||
1211 MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1212 MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:ResourceURI>") XML_CR
1213 MI_T("<wsman:SelectorSet>") XML_CR )) )
1214 return MI_RESULT_FAILED;
1215
1216 /* namespace (if present)*/
1217 if (self->nameSpace)
1218 {
1219 mike 1.1 }
1220
1221 /* Put properties */
1222 for ( i = 0; i < cd->numProperties; i++ )
1223 {
1224 const MI_PropertyDecl* pd = cd->properties[i];
1225 const void* value = (char*)self + pd->offset;
1226
1227 if ((pd->flags & MI_FLAG_KEY) == 0)
1228 continue;
1229
1230 /* skip null values */
1231 if (!_Field_GetExists(value,(MI_Type)pd->type))
1232 continue;
1233
1234 if (_PackValue(
1235 buf,
1236 PropertyTagWriter_EPR,
1237 pd->name, value,
1238 (MI_Type)pd->type) != MI_RESULT_OK)
1239 {
1240 mike 1.1 return MI_RESULT_FAILED;
1241 }
1242 }
1243
1244 /* close EPR */
1245 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:SelectorSet>") XML_CR
1246 MI_T("</wsa:ReferenceParameters>") XML_CR )) )
1247 return MI_RESULT_FAILED;
1248
1249 return MI_RESULT_OK;
1250 }
1251
1252 static MI_Boolean TestOctetStringQualifier(
1253 const MI_PropertyDecl* pd)
1254 {
1255 size_t i;
1256
1257 for (i = 0; i < pd->numQualifiers; i++)
1258 {
1259 const MI_Qualifier* q = pd->qualifiers[i];
1260
1261 mike 1.1 if (Zcasecmp(q->name, T("OctetString")) == 0
1262 && q->type == MI_BOOLEAN
1263 && q->value)
1264 {
1265 return *((const MI_Boolean*)q->value);
1266 }
1267 }
1268
1269 return MI_FALSE;
1270 }
1271
1272 static MI_Result _PackInstance(
1273 WSBuf* buf,
1274 const MI_Instance* instance,
1275 MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
1276 void* filterPropertyData,
1277 const MI_ClassDecl* castToClassDecl,
1278 MI_Uint32 flags,
1279 MI_Boolean embedded)
1280 {
1281 Instance* self = (Instance*)instance;
1282 mike 1.1 const MI_ClassDecl* cd = castToClassDecl ? castToClassDecl : self->classDecl;
1283 MI_Uint32 i;
1284
1285 /* Check for null arguments */
1286 if (!self || !buf)
1287 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1288
1289 /* For Object & EPR, add <Item> tag */
1290 if ((flags & WSMAN_ObjectAndEPRFlag) == WSMAN_ObjectAndEPRFlag)
1291 {
1292 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsman:Item>") XML_CR)))
1293 return MI_RESULT_FAILED;
1294 }
1295
1296 /* If object was requested */
1297 if ((flags & WSMAN_ObjectFlag) == WSMAN_ObjectFlag)
1298 {
1299 /* Put classname */
1300 if ( MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
1301 MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1302 MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/"))) ||
1303 mike 1.1 MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1304 MI_RESULT_OK != WSBuf_AddLit2(buf, '"', '\n'))
1305 return MI_RESULT_FAILED;
1306
1307 if (embedded)
1308 {
1309 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xsi:type=\""))) ||
1310 MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1311 MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("_Type\"") XML_CR)))
1312 return MI_RESULT_FAILED;
1313 }
1314 if ( MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
1315 return MI_RESULT_FAILED;
1316
1317 /* Put properties */
1318 for ( i = 0; i < cd->numProperties; i++ )
1319 {
1320 const MI_PropertyDecl* pd = cd->properties[i];
1321 const void* value = (char*)self + pd->offset;
1322 MI_Boolean isOctetString = MI_FALSE;
1323
1324 mike 1.1 if (filterProperty &&
1325 (*filterProperty)(pd->name, filterPropertyData))
1326 {
1327 continue;
1328 }
1329
1330 /* Search for OctetString qualifier */
1331
1332 if (pd->type == MI_UINT8A || pd->type == MI_STRINGA)
1333 isOctetString = TestOctetStringQualifier(pd);
1334
1335 /* Pack the field */
1336
1337 if (_PackField(
1338 buf,
1339 PropertyTagWriter_Prop,
1340 pd->name,
1341 value,
1342 (MI_Type)pd->type,
1343 isOctetString) != MI_RESULT_OK)
1344 {
1345 mike 1.1 return MI_RESULT_FAILED;
1346 }
1347 }
1348
1349 /* close class */
1350 if ( MI_RESULT_OK != WSBuf_AddLit4(buf, '<', '/', 'p', ':') ||
1351 MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1352 MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
1353 return MI_RESULT_FAILED;
1354 }
1355
1356 /* If EPR was requested */
1357 if ((flags & WSMAN_EPRFlag) == WSMAN_EPRFlag)
1358 {
1359 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsa:EndpointReference>") XML_CR)) ||
1360 MI_RESULT_OK != _PackEPR(buf,instance) ||
1361 MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsa:EndpointReference>") XML_CR)))
1362 return MI_RESULT_FAILED;
1363 }
1364
1365 /* If EPR was requested */
1366 mike 1.1 if ((flags & WSMAN_CreatedEPRFlag) == WSMAN_CreatedEPRFlag)
1367 {
1368 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wxf:ResourceCreated>") XML_CR)) ||
1369 MI_RESULT_OK != _PackEPR(buf,instance) ||
1370 MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wxf:ResourceCreated>") XML_CR)))
1371 return MI_RESULT_FAILED;
1372 }
1373
1374 /* For Object & EPR, add </Item> tag */
1375 if ((flags & WSMAN_ObjectAndEPRFlag) == WSMAN_ObjectAndEPRFlag)
1376 {
1377 if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:Item>") XML_CR)))
1378 return MI_RESULT_FAILED;
1379 }
1380
1381
1382 return MI_RESULT_OK;
1383 }
1384
1385 MI_Result WSBuf_InstanceToBuf(
1386 const MI_Instance* instance,
1387 mike 1.1 MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
1388 void* filterPropertyData,
1389 const MI_ClassDecl* castToClassDecl,
1390 Batch* batch,
1391 MI_Uint32 flags,
1392 void** ptrOut,
1393 MI_Uint32* sizeOut)
1394 {
1395 WSBuf buf;
1396 MI_Result r;
1397 Page* page;
1398
1399 r = WSBuf_Init(&buf,1024);
1400
1401 if (MI_RESULT_OK != r)
1402 return r;
1403
1404 r = _PackInstance(&buf, instance, filterProperty,
1405 filterPropertyData, castToClassDecl, flags,MI_FALSE);
1406
1407 if (MI_RESULT_OK != r)
1408 mike 1.1 {
1409 WSBuf_Destroy(&buf);
1410 return r;
1411 }
1412
1413 page = WSBuf_StealPage(&buf);
1414 Batch_AttachPage(batch, page);
1415
1416 *ptrOut = page + 1;
1417 *sizeOut = (MI_Uint32)page->u.s.size;
1418 return MI_RESULT_OK;
1419 }
1420
1421 void WSBuf_GenerateMessageID(
1422 MI_Char msgID[WS_MSG_ID_SIZE])
1423 {
1424 //WS-Management qualifies the use of wsa:MessageID and wsa:RelatesTo as follows:
1425 //R5.4.6.4-1: The MessageID and RelatesTo URIs may be of any format, as long as they are valid
1426 //URIs according to RFC 3986. Two URIs are considered different even if the characters in the
1427 //URIs differ only by case.
1428 //The following two formats are endorsed by this specification. The first is considered a best
1429 mike 1.1 //practice because it is backed by RFC 4122:
1430 //urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1431 //or
1432 //uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1433 //In these formats, each x is an uppercase or lowercase hexadecimal digit (lowercase is required
1434 //by RFC 4122); there are no spaces or other tokens. The value may be a DCE-style universally
1435 //unique identifier (UUID) with provable uniqueness properties in this format, however, it is not
1436 //necessary to have provable uniqueness properties in the URIs used in the wsa:MessageID and
1437 //wsa:RelatesTo headers.
1438 //Regardless of format, the URI should not exceed the maximum defined in R13.1-6.
1439 //UUIDs have a numeric meaning as well as a string meaning, and this can lead to confusion. A UUID
1440 //in lowercase is a different URI from the same UUID in uppercase. This is because URIs are case1619
1441 //tive. If a UUID is converted to its decimal equivalent the case of the original characters is lost.
1442 //WS-Management works with the URI value itself, not the underlying decimal equivalent
1443 //representation. Services are free to interpret the URI in any way, but are not allowed to alter the case
1444 //usage when repeating the message or any of the MessageID values in subsequent messages.
1445 //The RFC 4122 requires the digits to be lowercase, which is the responsibility of the client. The service
1446 //simply processes the values as URI values and is not required to analyze the URI for correctness or
1447 //compliance. The service replicates the client usage in the wsa:RelatesTo reply header and is not
1448 //allowed to alter the case usage.
1449 //R5.4.6.4-2: The MessageID should be generated according to any algorithm that ensures that no
1450 mike 1.1 //two MessageIDs are repeated. Because the value is treated as case-sensitive (R5.4.6.4-1),
1451 //confusion can arise if the same value is reused differing only in case. As a result, the service shall
1452 //not create or employ MessageID values that differ only in case. For any message transmitted by
1453 //the service, the MessageID shall not be reused.
1454
1455 static MI_Uint64 s1, s2;
1456
1457 if (!s1)
1458 Time_Now(&s1);
1459
1460 s2++;
1461
1462 /* ADC */
1463 if (!s2)
1464 s1++;
1465
1466 Szprintf(msgID, WS_MSG_ID_SIZE,
1467 MI_T("uuid:%08X-%04X-%04X-%04X-%08X%04X"),
1468 (MI_Uint32)(s1 & 0xFFFFFFFF),
1469 (MI_Uint32)((s1 >> 32) & 0xFFFF),
1470 (MI_Uint32)((s1 >> 48) & 0xFFFF),
1471 mike 1.1 (MI_Uint32)((s2 >> 48) & 0xFFFF),
1472 (MI_Uint32)(s2 & 0xFFFFFFFF),
1473 (MI_Uint32)((s2 >> 32) & 0xFFFF) );
1474 }
1475
1476 MI_Result WSBuf_CreateSoapResponseHeader(
1477 WSBuf *buf,
1478 const MI_Char* action,
1479 MI_Uint32 actionSize,
1480 const char* relatesTo)
1481 {
1482 MI_Char msgID[WS_MSG_ID_SIZE];
1483
1484 /* Response header */
1485 if (MI_RESULT_OK != WSBuf_AddLit(buf,
1486 LIT(
1487 MI_T("<SOAP-ENV:Envelope ")
1488 MI_T("xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" ")
1489 MI_T("xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" ")
1490 MI_T("xmlns:wsen=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\" ")
1491 MI_T("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ")
1492 mike 1.1 MI_T("xmlns:wsmb=\"http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd\" ")
1493 MI_T("xmlns:wsman=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\" ")
1494 MI_T("xmlns:wxf=\"http://schemas.xmlsoap.org/ws/2004/09/transfer\" ")
1495 MI_T("xmlns:xml=\"http://www.w3.org/XML/1998/namespace\" ")
1496 MI_T("xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\" >")
1497 XML_CR
1498 MI_T("<SOAP-ENV:Header>") XML_CR
1499 MI_T("<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>") XML_CR
1500 MI_T("<wsa:Action>"))) )
1501 {
1502 goto failed;
1503 }
1504
1505 if (MI_RESULT_OK != WSBuf_AddLit(buf, action, actionSize))
1506 goto failed;
1507
1508 if (MI_RESULT_OK != WSBuf_AddLit(buf,
1509 LIT(MI_T("</wsa:Action>") XML_CR
1510 MI_T("<wsa:MessageID>" ))))
1511 goto failed;
1512
1513 mike 1.1 /* Generate new uniqueue msg id */
1514 WSBuf_GenerateMessageID(msgID);
1515
1516 if (MI_RESULT_OK != WSBuf_AddLit(buf, msgID, WS_MSG_ID_SIZE - 1))
1517 goto failed;
1518
1519 if (MI_RESULT_OK != WSBuf_AddLit(buf,
1520 LIT(MI_T("</wsa:MessageID>") XML_CR)))
1521 goto failed;
1522
1523 if (relatesTo)
1524 {
1525 if (MI_RESULT_OK != WSBuf_AddLit(buf,
1526 LIT(MI_T("<wsa:RelatesTo>"))))
1527 goto failed;
1528
1529 if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(buf, relatesTo))
1530 goto failed;
1531
1532 if (MI_RESULT_OK != WSBuf_AddLit(buf,
1533 LIT(MI_T("</wsa:RelatesTo>") XML_CR)))
1534 mike 1.1 goto failed;
1535 }
1536
1537 return MI_RESULT_OK;
1538
1539 failed:
1540 return MI_RESULT_FAILED;
1541 }
1542
1543
1544
1545 Page* WSBuf_CreateFaultResponsePage(
1546 WSBUF_FAULT_CODE faultCode,
1547 const char* notUnderstoodTag,
1548 const char* requestMessageID,
1549 const MI_Char* descriptionText)
1550 {
1551 WSBuf outBuf;
1552 const BUF_FaultItem* fault;
1553
1554 if ( ((MI_Uint32)faultCode) >= MI_COUNT(s_faults))
1555 mike 1.1 {
1556 fault = s_faults + 0; /* internal error */
1557 }
1558 else
1559 {
1560 fault = s_faults + (MI_Uint32)faultCode;
1561 }
1562
1563
1564 /* prepare soap response with error */
1565 if (WSBuf_Init(&outBuf, 1024) != MI_RESULT_OK)
1566 return 0;
1567
1568 /* fault header */
1569 if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
1570 fault->action, fault->actionSize, requestMessageID))
1571 goto failed;
1572
1573 if (notUnderstoodTag)
1574 {
1575 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1576 mike 1.1 LIT(MI_T("<SOAP-ENV:NotUnderstood qname=\""))))
1577 goto failed;
1578
1579 if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, notUnderstoodTag ))
1580 goto failed;
1581
1582 if (MI_RESULT_OK != WSBuf_AddLit3(&outBuf, '"', '/', '>'))
1583 goto failed;
1584 }
1585
1586 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1587 LIT(
1588 MI_T("</SOAP-ENV:Header>") XML_CR XML_CR
1589 MI_T("<SOAP-ENV:Body>") XML_CR
1590 MI_T("<SOAP-ENV:Fault>") XML_CR
1591 MI_T("<SOAP-ENV:Code>") XML_CR
1592 MI_T("<SOAP-ENV:Value>"))) )
1593 goto failed;
1594
1595 if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->code))
1596 goto failed;
1597 mike 1.1 //SOAP-ENV:Sender
1598
1599 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1600 LIT(MI_T("</SOAP-ENV:Value>") XML_CR)))
1601 goto failed;
1602
1603 if (fault->subCode)
1604 {
1605 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1606 LIT(MI_T("<SOAP-ENV:Subcode>") XML_CR
1607 MI_T("<SOAP-ENV:Value>"))))
1608 goto failed;
1609
1610 if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->subCode))
1611 goto failed;
1612
1613 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1614 LIT(MI_T("</SOAP-ENV:Value>") XML_CR
1615 MI_T("</SOAP-ENV:Subcode>") XML_CR)))
1616 goto failed;
1617 }
1618 mike 1.1
1619 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1620 LIT(MI_T("</SOAP-ENV:Code>") XML_CR
1621 MI_T("<SOAP-ENV:Reason>") XML_CR
1622 MI_T("<SOAP-ENV:Text xml:lang=\"en-US\">"))))
1623 goto failed;
1624
1625 if ( descriptionText )
1626 {
1627 if (MI_RESULT_OK != WSBuf_AddString(&outBuf, descriptionText))
1628 goto failed;
1629 }
1630 else
1631 {
1632 if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->defaultTest))
1633 goto failed;
1634 }
1635
1636 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1637 LIT( MI_T("</SOAP-ENV:Text>") XML_CR
1638 MI_T("</SOAP-ENV:Reason>") XML_CR
1639 mike 1.1 MI_T("</SOAP-ENV:Fault>") XML_CR
1640 MI_T("</SOAP-ENV:Body>") XML_CR
1641 MI_T("</SOAP-ENV:Envelope>") XML_CR)) )
1642 goto failed;
1643
1644
1645 return WSBuf_StealPage(&outBuf);
1646
1647 failed:
1648
1649 WSBuf_Destroy(&outBuf);
1650 return 0;
1651 }
1652
1653 Page* WSBuf_CreateReleaseResponsePage(
1654 const char* requestMessageID)
1655 {
1656 WSBuf outBuf;
1657
1658 /* prepare soap response with error */
1659 if (WSBuf_Init(&outBuf, 1024) != MI_RESULT_OK)
1660 mike 1.1 return 0;
1661
1662 /* fault header */
1663 if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
1664 LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/09/enumeration/ReleaseResponse")),
1665 requestMessageID))
1666 goto failed;
1667
1668 if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1669 LIT(
1670 MI_T("</SOAP-ENV:Header>") XML_CR XML_CR
1671 MI_T("<SOAP-ENV:Body/>") XML_CR
1672 MI_T("</SOAP-ENV:Envelope>") XML_CR)) )
1673 goto failed;
1674
1675 return WSBuf_StealPage(&outBuf);
1676
1677 failed:
1678
1679 WSBuf_Destroy(&outBuf);
1680 return 0;
1681 mike 1.1 }
1682
1683 WSBUF_FAULT_CODE WSBuf_CIMErrorToWSFault(
1684 MI_Uint32 cimErrorCode,
1685 const MI_Char** description )
1686 {
1687 MI_Uint32 index = cimErrorCode < MI_COUNT(s_cimerrors) ? cimErrorCode : MI_RESULT_FAILED;
1688
1689 if ( description )
1690 *description = s_cimerrors[index].description;
1691
1692 return s_cimerrors[index].faultCode;
1693 }
|