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