1 krisbash 1.1 /*============================================================================
2 * Copyright (C) Microsoft Corporation, All rights reserved.
3 *============================================================================
4 */
5 #include <stdio.h>
6 #include <common.h>
7 #include <pal/strings.h>
8 #include <pal/format.h>
9 #include <base/log.h>
10 #include <base/helpers.h>
11 #include <base/class.h>
12 #include <base/instance.h>
13 #include <base/types.h>
14 #include <base/field.h>
15 #include "xmlserializer.h"
16
17 //******************************************XMLSERIALIZER Creation/Deletion************************
18
19 /* Create serializer object */
20 MI_Result MI_CALL XmlSerializer_Create(
21 _In_ MI_Application *application,
22 krisbash 1.1 MI_Uint32 flags,
23 _In_z_ MI_Char *format,
24 _Out_ MI_Serializer *serializer)
25 {
26 if ((application == NULL) || (flags != 0) || (format == NULL) || (serializer == NULL))
27 {
28 return MI_RESULT_INVALID_PARAMETER;
29 }
30 if (Tcscmp(format, PAL_T("MI_XML")) != 0) //TODO: Case sensitive?
31 {
32 return MI_RESULT_NOT_SUPPORTED;
33 }
34 memset(serializer, 0, sizeof(*serializer));
35
36 return MI_RESULT_OK;
37 }
38
39 /* Close serializer object */
40 MI_Result MI_CALL XmlSerializer_Close(
41 _Inout_ MI_Serializer *serializer)
42 {
43 krisbash 1.1 return MI_RESULT_OK;
44 }
45
46 //******************************************Class Serialization logic************************
47 #define IsOptionTrue(flags, option) ((flags & (option)) != 0)
48 #define SERIALIZE_NO_ESCAPE 0
49
50 //Length of string literal
51 #define WCSLEN(string) ((sizeof(string)/sizeof(string[0]))-1)
52
53 /* Preferred write mechanism for string literal to the buffer. We do sizeof string which is a compile-time calculation. */
54 #define WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferUsed, bufferToWrite, escapingDepth, result) WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferUsed, bufferToWrite, WCSLEN(bufferToWrite), escapingDepth, result)
55
56 /* Preferred write mechanism as we don't need to Tcslen the buffer to write */
57 static void WriteBuffer_StringWithLength(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferNeeded, _In_reads_z_(bufferToWriteLength) const MI_Char *bufferToWrite, MI_Uint32 bufferToWriteLength, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
58
59 /* Don't use unless we really don't know the length as we will Tcslen the buffer to write */
60 #define WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferUsed, bufferToWrite, escapingDepth, result) WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferUsed, bufferToWrite, Tcslen(bufferToWrite), escapingDepth, result)
61
62 /* writes the textual version of MI_Type */
63 static void WriteBuffer_MiType(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferUsed, MI_Type type, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
64 krisbash 1.1
65 /* writes the textual version of MI_Array based on MI_Type. */
66 static void WriteBuffer_MiValueArray(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferUsed, MI_Type type, _In_ const MI_Array *value, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
67
68 /* writes the textual version of MI_Value based on MI_Type. */
69 static void WriteBuffer_MiValue(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferUsed, MI_Type type, _In_opt_ const MI_Value *value, MI_Boolean includeTags, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
70
71 /* writes the textual version of MI_Qualifier array. */
72 static void WriteBuffer_MiQualifierSet(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferUsed, _In_ const MI_QualifierSet *qualifierSet, MI_Uint32 flagsToSerializeAsQualifiers, MI_Boolean isQualOnInheritedElement, _Inout_ MI_Result *result);
73 static void WriteBuffer_MiParamPropertyQualifierSet(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferUsed, _In_ const MI_QualifierSet *qualifierSet, MI_Uint32 flagsToSerializeAsQualifiers, MI_Boolean isQualOnInheritedElement, MI_Boolean isEmbeddedProperty, _In_opt_ const MI_Char *referenceClassForEmbeddedProperty, _Inout_ MI_Result *result);
74 static void WriteBuffer_EmbeddedPropertyQualifier(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferNeeded, _In_opt_ const MI_Char *referenceClassForEmbeddedProperty, _Inout_ MI_Result *result);
75
76 static void WriteBuffer_MiFlagQualifiers(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,MI_Uint32 clientBufferLength,_Inout_ MI_Uint32 *clientBufferNeeded,MI_Uint32 flagsToSerializeAsQualifiers,_Inout_ MI_Result *result);
77
78 /* writes the textual version of %CIMName. (name="name") */
79 static void WriteBuffer_CimName(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferUsed, _In_z_ const MI_Char* name, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
80
81 static void WriteBuffer_Uint32(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferNeeded, MI_Uint32 number, _Inout_ MI_Result *result);
82
83 static void WriteBuffer_SerializeClass(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferNeeded, MI_Uint32 flags, _In_ const MI_Class *miClass, _In_opt_z_ const MI_Char *namespaceName,_In_opt_z_ const MI_Char *serverName,_Out_ MI_Result *result);
84
85 krisbash 1.1 static void WriteBuffer_Instance(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,MI_Uint32 clientBufferLength,_Inout_ MI_Uint32 *clientBufferNeeded,_In_ const MI_Instance *instance,MI_Uint32 escapingDepth, _Out_ MI_Result *result);
86 static void WriteBuffer_InstanceReference(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,MI_Uint32 clientBufferLength,_Inout_ MI_Uint32 *clientBufferNeeded,_In_opt_z_ const MI_Char *namespaceName, _In_opt_z_ const MI_Char *serverName, _In_ const MI_Instance *refValue, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
87
88 static void WriteBuffer_MiPropertyDecls(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer, MI_Uint32 clientBufferLength, _Inout_ MI_Uint32 *clientBufferNeeded, _In_ const MI_Class *miClass, MI_Uint32 flags, _In_z_ const MI_Char *className,_In_opt_z_ const MI_Char *namespaceName, _In_opt_z_ const MI_Char *serverName , _In_opt_ const char *instanceStart, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
89
90 //Write an instance parameter MI_<type>Field
91 static void WriteBuffer_MiTypeField(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,MI_Uint32 clientBufferLength,_Inout_ MI_Uint32 *clientBufferNeeded,MI_Type type,_In_ const char *fieldValue, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
92
93 //Write an instance array parameter MI_ArrayField
94 static void WriteBuffer_MiArrayField(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,MI_Uint32 clientBufferLength,_Inout_ MI_Uint32 *clientBufferNeeded,MI_Type type,_In_ MI_ArrayField *arrayField, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
95
96 static void WriteBuffer_NAMESPACEPATH(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,MI_Uint32 clientBufferLength,_Inout_ MI_Uint32 *clientBufferNeeded,_In_z_ const MI_Char *namespaceName, _In_z_ const MI_Char *serverName, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
97 static void WriteBuffer_LOCALNAMESPACEPATH(_Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,MI_Uint32 clientBufferLength,_Inout_ MI_Uint32 *clientBufferNeeded,_In_z_ const MI_Char *namespaceName, MI_Uint32 escapingDepth, _Inout_ MI_Result *result);
98
99 static void WriteBuffer_Instance(
100 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
101 MI_Uint32 clientBufferLength,
102 _Inout_ MI_Uint32 *clientBufferNeeded,
103 _In_ const MI_Instance *instance_,
104 MI_Uint32 escapingDepth,
105 _Out_ MI_Result *result)
106 krisbash 1.1 {
107 // No one is using OSC_Instance structure inside OMI;
108 // so I am assuming all instances here are going to be MI_Instances
109 // so getting rid of this OSC_Instance from the reused code and replacing it with MI_Instance
110 // in the future if someone adds OSC_Instance in OMI then add this back
111 // MI_Instance *instance = (MI_Instance*)((OSC_Instance*)instance_)->self; //In case this is dynamic instance point to the real one, otherwise it points to ourself!
112 const MI_Instance *instance = instance_;
113 MI_Class classOfInstance = MI_CLASS_NULL;
114 const MI_Char *classNameOfInstance = NULL;
115
116 *result = MI_RESULT_OK;
117
118 *result = MI_Instance_GetClassExt(instance, &classOfInstance);
119
120 *result = GetClassExtendedFt(&classOfInstance)->GetClassName(&classOfInstance, &classNameOfInstance);
121
122 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<INSTANCE"), escapingDepth, result);
123
124 /* %ClassName; */
125 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" CLASSNAME=\""), escapingDepth, result);
126 if(classNameOfInstance)
127 krisbash 1.1 {
128 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, classNameOfInstance, escapingDepth, result);
129 }
130 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), escapingDepth, result);
131
132 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), escapingDepth, result);
133
134 /* PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE */
135 // casting done since it does not compile on non-windows
136 WriteBuffer_MiPropertyDecls(clientBuffer, clientBufferLength, clientBufferNeeded, &classOfInstance, MI_TRUE, classNameOfInstance, instance->nameSpace, instance->serverName, (char*)instance, escapingDepth, result);
137
138 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</INSTANCE>"), escapingDepth, result);
139 }
140
141 static void WriteBuffer_SerializeClass(
142 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
143 MI_Uint32 clientBufferLength,
144 _Inout_ MI_Uint32 *clientBufferNeeded,
145 MI_Uint32 flags,
146 _In_ const MI_Class *miClass,
147 _In_opt_z_ const MI_Char *namespaceName,
148 krisbash 1.1 _In_opt_z_ const MI_Char *serverName,
149 _Out_ MI_Result *result)
150 {
151 const MI_Char *miClassName = NULL;
152 const MI_Char *miParentClassName = NULL;
153 MI_QualifierSet qualifierSet;
154 MI_Uint32 numQualifiers = 0;
155
156 *result = MI_RESULT_OK;
157 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<CLASS"), SERIALIZE_NO_ESCAPE, result);
158
159 /* %CIMName; */
160 *result = GetClassExtendedFt(miClass)->GetClassName(miClass, &miClassName);
161 if(miClassName)
162 {
163 WriteBuffer_CimName(clientBuffer, clientBufferLength, clientBufferNeeded, miClassName, SERIALIZE_NO_ESCAPE, result);
164 }
165
166 /* %SuperClass; */
167 GetClassExtendedFt(miClass)->GetParentClassName(miClass, &miParentClassName);
168 if (miParentClassName)
169 krisbash 1.1 {
170 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" SUPERCLASS=\""), SERIALIZE_NO_ESCAPE, result);
171 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, miParentClassName, SERIALIZE_NO_ESCAPE, result);
172 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), SERIALIZE_NO_ESCAPE, result);
173 }
174
175 /* %DERIVATION; */
176 if(IsOptionTrue(flags, MI_SERIALIZER_FLAGS_INCLUDE_INHERITANCE_HIERARCHY))
177 {
178 const MI_Class *currentClass = miClass;
179 MI_Class currentSuperClass;
180 MI_Uint32 countOfClasses = 0;
181
182 GetClassExtendedFt(currentClass)->GetParentClassExt(currentClass, ¤tSuperClass);
183
184 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" DERIVATION=\""), SERIALIZE_NO_ESCAPE, result);
185 while(miParentClassName)
186 {
187 trace_XmlSerializer_CurrentParent(tcs(miParentClassName));
188
189 // before writing first superclassname; you would not need a separator otherwise you will
190 krisbash 1.1 if(countOfClasses != 0)
191 {
192 // preventing infinite loop
193 if(countOfClasses == 0xFFFFFFFF)
194 {
195 *result = MI_RESULT_FAILED;
196 return;
197 }
198
199 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(","), SERIALIZE_NO_ESCAPE, result);
200 }
201
202 #ifdef _MSC_VER
203 #pragma prefast(push)
204 #pragma prefast (disable: 26018)
205 #endif
206 // write the super class name in the list
207 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, miParentClassName, SERIALIZE_NO_ESCAPE, result);
208
209 #ifdef _MSC_VER
210 #pragma prefast(pop)
211 krisbash 1.1 #endif
212
213 // clear out the classname we just wrote
214 miParentClassName = NULL;
215
216 // go up one level in the parent chain
217 currentClass = ¤tSuperClass;
218
219 // if there is still a superclass, get its name
220 if(GetClassExtendedFt(currentClass)->GetParentClassExt(currentClass, ¤tSuperClass) == MI_RESULT_OK)
221 {
222 *result = GetClassExtendedFt(¤tSuperClass)->GetClassName(¤tSuperClass, &miParentClassName);
223 }
224
225 countOfClasses++;
226 }
227
228 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), SERIALIZE_NO_ESCAPE, result);
229 }
230
231 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), SERIALIZE_NO_ESCAPE, result);
232 krisbash 1.1
233 /* QUALIFIERS */
234 if(IsOptionTrue(flags, MI_SERIALIZER_FLAGS_INCLUDE_QUALIFIERS))
235 {
236 MI_Uint32 classFlags = 0;
237 GetClassExtendedFt(miClass)->GetClassQualifierSet(miClass, &qualifierSet);
238 GetQualifierSetFt(&qualifierSet)->GetQualifierCount(&qualifierSet, &numQualifiers);
239 GetClassExtendedFt(miClass)->GetClassFlagsExt(miClass, &classFlags);
240 WriteBuffer_MiQualifierSet(clientBuffer, clientBufferLength, clientBufferNeeded, &qualifierSet, classFlags, MI_FALSE, result);
241 }
242
243 /* PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE */
244 WriteBuffer_MiPropertyDecls(clientBuffer, clientBufferLength, clientBufferNeeded, miClass, flags, miClassName, namespaceName, serverName, NULL, SERIALIZE_NO_ESCAPE, result);
245
246 /* METHOD */
247 {
248 MI_Uint32 methodCount;
249 MI_Uint32 totalMethodCount;
250 MI_Uint32 parameterCount;
251 const MI_Char *methodName = NULL;
252 MI_QualifierSet methodQualifierSet;
253 krisbash 1.1 MI_ParameterSet parameterSet;
254 MI_Uint32 methodParameterCount;
255 const MI_Char *parameterName = NULL;
256 MI_Type parameterType;
257 MI_Uint32 parameterSubscript;
258 MI_Char *referenceClass = NULL;
259 MI_Char *methodOriginClass = NULL;
260 MI_Char *methodPropagatorClass = NULL;
261 MI_QualifierSet parameterQualifierSet;
262 MI_Uint32 methodFlags = 0;
263 MI_Uint32 parameterFlags = 0;
264
265 GetClassExtendedFt(miClass)->GetMethodCount(miClass, &totalMethodCount);
266
267 for (methodCount = 0; methodCount != totalMethodCount; methodCount++)
268 {
269 MI_Boolean isInheritedElement = MI_FALSE;
270
271 GetClassExtendedFt(miClass)->GetMethodAtExt(miClass, methodCount, &methodName, &methodOriginClass, &methodPropagatorClass, &methodQualifierSet, ¶meterSet, &methodFlags);
272
273 /* If not serializing deep and we are not the propagator of the property then we need to skip this one */
274 krisbash 1.1 if (!IsOptionTrue(flags, MI_SERIALIZER_FLAGS_CLASS_DEEP | MI_SERIALIZER_FLAGS_INCLUDE_INHERITED_ELEMENTS) && methodPropagatorClass && Tcscmp(methodPropagatorClass, miClassName)!=0)
275 {
276 continue;
277 }
278 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<METHOD"), SERIALIZE_NO_ESCAPE, result);
279
280 /* %CIMName; */
281 WriteBuffer_CimName(clientBuffer, clientBufferLength, clientBufferNeeded, methodName, SERIALIZE_NO_ESCAPE, result);
282
283 GetParameterSetExtendedFt(¶meterSet)->GetParameterCount(¶meterSet, &methodParameterCount);
284
285 GetParameterSetExtendedFt(¶meterSet)->GetMethodReturnType(¶meterSet, ¶meterType, ¶meterQualifierSet);
286
287 /* %CIMType; */
288 WriteBuffer_MiType(clientBuffer, clientBufferLength, clientBufferNeeded, (MI_Type)(parameterType&~MI_ARRAY), SERIALIZE_NO_ESCAPE, result);
289
290 /* %ClassOrigin; */
291 if (IsOptionTrue(flags, MI_SERIALIZER_FLAGS_INCLUDE_CLASS_ORIGIN) &&
292 methodOriginClass)
293 {
294 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" CLASSORIGIN=\""), SERIALIZE_NO_ESCAPE, result);
295 krisbash 1.1 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, methodOriginClass, SERIALIZE_NO_ESCAPE, result);
296 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), SERIALIZE_NO_ESCAPE, result);
297 }
298 /* %Propagated; */
299 if (methodPropagatorClass &&
300 (Tcscasecmp(methodPropagatorClass, miClassName) != 0))
301 {
302 isInheritedElement = MI_TRUE;
303 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" PROPAGATED=\"true\""), SERIALIZE_NO_ESCAPE, result);
304 }
305
306 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), SERIALIZE_NO_ESCAPE, result);
307
308 /* QUALIFIERS */
309 if(IsOptionTrue(flags, MI_SERIALIZER_FLAGS_INCLUDE_QUALIFIERS))
310 {
311 WriteBuffer_MiQualifierSet(clientBuffer, clientBufferLength, clientBufferNeeded, &methodQualifierSet, methodFlags, isInheritedElement, result);
312 }
313
314 /* even though this loop starts from 0, the GetParameterAt method increments the index passed to it so we will get the parameters from the index 1 */
315 for (parameterCount = 0; parameterCount < methodParameterCount; parameterCount++)
316 krisbash 1.1 {
317 GetParameterSetExtendedFt(¶meterSet)->GetParameterAtExt(¶meterSet, parameterCount, ¶meterName, ¶meterType,
318 ¶meterSubscript, &referenceClass, ¶meterQualifierSet, ¶meterFlags);
319
320 /* Start of PARAMETER | PARAMETER.REFERENCE | PARAMETER_ARRAY | PARAMETER.REFARRAY */
321 if (parameterType == MI_REFERENCE)
322 {
323 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<PARAMETER.REFERENCE"), SERIALIZE_NO_ESCAPE, result);
324 }
325 else if (parameterType == MI_REFERENCEA)
326 {
327 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<PARAMETER.REFARRAY"), SERIALIZE_NO_ESCAPE, result);
328 }
329 else if (parameterType & MI_ARRAY)
330 {
331 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<PARAMETER.ARRAY"), SERIALIZE_NO_ESCAPE, result);
332 }
333 else
334 {
335 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<PARAMETER"), SERIALIZE_NO_ESCAPE, result);
336 }
337 krisbash 1.1 /* %CIMName; */
338 WriteBuffer_CimName(clientBuffer, clientBufferLength, clientBufferNeeded, parameterName, SERIALIZE_NO_ESCAPE, result);
339
340 if ((parameterType != MI_REFERENCE) &&
341 (parameterType != MI_REFERENCEA))
342 {
343 /* %CIMType; -- PARAMETER and PARAMETER.ARRAY */
344 WriteBuffer_MiType(clientBuffer, clientBufferLength, clientBufferNeeded, parameterType, SERIALIZE_NO_ESCAPE, result);
345 }
346 else if (referenceClass)
347 {
348 /* %ReferenceClass; -- PROPERTY.REFERENCE and PROPERTY.REFARRAY*/
349 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" REFERENCECLASS=\""), SERIALIZE_NO_ESCAPE, result);
350 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, referenceClass, SERIALIZE_NO_ESCAPE, result);
351 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), SERIALIZE_NO_ESCAPE, result);
352 }
353
354 if ((parameterType & MI_ARRAY) &&
355 (parameterSubscript != 0))
356 {
357 /* %ArraySize; -- PROPERTY.ARRAY and PROPERTY.REFARRAY */
358 krisbash 1.1 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" ARRAYSIZE=\""), SERIALIZE_NO_ESCAPE, result);
359 WriteBuffer_Uint32(clientBuffer, clientBufferLength, clientBufferNeeded, parameterSubscript, result);
360 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), SERIALIZE_NO_ESCAPE, result);
361 }
362
363 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), SERIALIZE_NO_ESCAPE, result);
364
365 /* QUALIFIERS */
366 if(IsOptionTrue(flags, MI_SERIALIZER_FLAGS_INCLUDE_QUALIFIERS))
367 {
368 WriteBuffer_MiParamPropertyQualifierSet(clientBuffer, clientBufferLength, clientBufferNeeded, ¶meterQualifierSet, parameterFlags, MI_FALSE, ((parameterType&~MI_ARRAY) == MI_INSTANCE), referenceClass, result);
369 }
370
371 /* End of PARAMETER | PARAMETER.REFERENCE | PARAMETER_ARRAY | PARAMETER.REFARRAY */
372 if (parameterType == MI_REFERENCE)
373 {
374 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</PARAMETER.REFERENCE>"), SERIALIZE_NO_ESCAPE, result);
375 }
376 else if (parameterType == MI_REFERENCEA)
377 {
378 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</PARAMETER.REFARRAY>"), SERIALIZE_NO_ESCAPE, result);
379 krisbash 1.1 }
380 else if (parameterType & MI_ARRAY)
381 {
382 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</PARAMETER.ARRAY>"), SERIALIZE_NO_ESCAPE, result);
383 }
384 else
385 {
386 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</PARAMETER>"), SERIALIZE_NO_ESCAPE, result);
387 }
388 }
389
390 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</METHOD>"), SERIALIZE_NO_ESCAPE, result);
391 }
392 }
393
394 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</CLASS>"), SERIALIZE_NO_ESCAPE, result);
395 }
396
397 static void WriteBuffer_MiPropertyDecls(
398 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
399 MI_Uint32 clientBufferLength,
400 krisbash 1.1 _Inout_ MI_Uint32 *clientBufferNeeded,
401 _In_ const MI_Class *miClass,
402 MI_Uint32 flags,
403 _In_z_ const MI_Char *className,
404 _In_opt_z_ const MI_Char *namespaceName,
405 _In_opt_z_ const MI_Char *serverName,
406 _In_opt_ const char *instanceStart,
407 MI_Uint32 escapingDepth,
408 _Inout_ MI_Result *result)
409 {
410 MI_Uint32 propertyCount;
411 MI_Uint32 totalPropertyCount;
412 MI_Value propertyValue;
413 MI_Type propertyType;
414 MI_Uint32 propertyFlags;
415 MI_Uint32 propertySubscript;
416 MI_Uint32 propertyOffset;
417 MI_QualifierSet propertyQualifierSet;
418 const MI_Char *propertyName = NULL;
419 MI_Char *propertyReferenceClass = NULL;
420 MI_Char *propertyOriginClass = NULL;
421 krisbash 1.1 MI_Char *propertyPropagatorClass = NULL;
422
423 GetClassExtendedFt(miClass)->GetElementCount(miClass, &totalPropertyCount);
424
425 /* PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE */
426 for (propertyCount = 0; propertyCount != totalPropertyCount; propertyCount++)
427 {
428 MI_Boolean propertyValueExists = MI_TRUE;
429 MI_Boolean isInheritedElement = MI_FALSE;
430
431 GetClassExtendedFt(miClass)->GetElementAtExt(miClass, propertyCount, &propertyName, &propertyValue, &propertyValueExists,
432 &propertyType, &propertySubscript, &propertyOffset , &propertyReferenceClass, &propertyOriginClass, &propertyPropagatorClass, &propertyQualifierSet, &propertyFlags);
433
434 /* If not serializing deep and we are not the propagator of the property then we need to skip this one */
435 //MI_SERIALIZER_FLAGS_CLASS_DEEP
436 if (!IsOptionTrue(flags, MI_SERIALIZER_FLAGS_CLASS_DEEP | MI_SERIALIZER_FLAGS_INCLUDE_INHERITED_ELEMENTS)
437 && propertyPropagatorClass && Tcscmp(propertyPropagatorClass, className)!=0)
438 {
439 continue;
440 }
441 else
442 krisbash 1.1 {
443 trace_XmlSerializer_WriteBuffer_MiPropertyDecls(tcs(className), tcs(propertyPropagatorClass), tcs(propertyName));
444 }
445
446 if (propertyType & MI_ARRAY)
447 {
448 if (propertyType == MI_REFERENCEA)
449 {
450 //Properties of type referenceArray cannot be supported. It is not CIM compliant
451 //Overwrite error as this is a hard error.
452 *result = MI_RESULT_NOT_SUPPORTED;
453 return;
454 }
455 else
456 {
457 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<PROPERTY.ARRAY"), escapingDepth, result);
458 }
459 }
460 else if (propertyType == MI_REFERENCE)
461 {
462 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<PROPERTY.REFERENCE"), escapingDepth, result);
463 krisbash 1.1 }
464 else
465 {
466 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<PROPERTY"), escapingDepth, result);
467 }
468
469 /* %CIMName; */
470 WriteBuffer_CimName(clientBuffer, clientBufferLength, clientBufferNeeded, propertyName, escapingDepth, result);
471
472 if ((propertyType != MI_REFERENCE) &&
473 (propertyType != MI_REFERENCEA))
474 {
475 /* %CIMType; -- not REFERENCE */
476 WriteBuffer_MiType(clientBuffer, clientBufferLength, clientBufferNeeded, propertyType, escapingDepth, result);
477 }
478 else if (!instanceStart &&
479 propertyReferenceClass &&
480 (propertyType == MI_REFERENCE))
481 {
482 /* %ReferenceClass; -- REFERENCE only and for classes only */
483 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" REFERENCECLASS=\""), escapingDepth, result);
484 krisbash 1.1 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, propertyReferenceClass, escapingDepth, result);
485 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), escapingDepth, result);
486 }
487
488 /* %ArraySize; -- property arays */
489 if ((propertyType & MI_ARRAY) && propertySubscript)
490 {
491 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" ARRAYSIZE=\""), escapingDepth, result);
492 WriteBuffer_Uint32(clientBuffer, clientBufferLength, clientBufferNeeded, propertySubscript, result);
493 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), escapingDepth, result);
494 }
495
496 /* %ClassOrigin; --implied if it is in the same class? */
497 if (IsOptionTrue(flags, MI_SERIALIZER_FLAGS_INCLUDE_CLASS_ORIGIN) &&
498 !instanceStart && propertyOriginClass)
499 {
500 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" CLASSORIGIN=\""), escapingDepth, result);
501 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, propertyOriginClass, escapingDepth, result);
502 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), escapingDepth, result);
503 }
504
505 krisbash 1.1 /* %Propagated; -- false is default, so only needed if it is true */
506 if (!instanceStart && propertyPropagatorClass && (Tcscmp(propertyPropagatorClass, className) != 0))
507 {
508 isInheritedElement = MI_TRUE;
509 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" PROPAGATED=\"true\""), escapingDepth, result);
510 }
511 /* %EmbeddedObject; -- type=MI_INSTANCE/MI_INSTANCEA for instances only, class does not have this--class has qualifier */
512 if (instanceStart &&
513 ((propertyType == MI_INSTANCE) ||
514 (propertyType == MI_INSTANCEA)))
515 {
516 if (propertyReferenceClass == NULL)
517 {
518 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" EmbeddedObject=\"object\""), escapingDepth, result);
519 }
520 else
521 {
522 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" EmbeddedObject=\"instance\" EmbeddedClassName=\""), escapingDepth, result);
523 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, propertyReferenceClass, escapingDepth, result);
524 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), escapingDepth, result);
525 }
526 krisbash 1.1 }
527 /* MODIFIED is our own attribute that handles the property flag MI_FLAG_NOT_MODIFIED. It is only relevant for instances. */
528 if (instanceStart)
529 {
530 MI_Uint32 flag = Field_GetFlagsExt(propertyType, (Field *)instanceStart+propertyOffset);
531
532 if ((flag & MI_FLAG_NOT_MODIFIED) == 0)
533 {
534 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" MODIFIED=\"TRUE\""), escapingDepth, result);
535 }
536 if (flag & MI_FLAG_NULL)
537 {
538 propertyValueExists = MI_FALSE;
539 }
540 }
541
542 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), escapingDepth, result);
543
544 /* QUALIFIERS -- class only*/
545 if (!instanceStart && IsOptionTrue(flags, MI_SERIALIZER_FLAGS_INCLUDE_QUALIFIERS))
546 {
547 krisbash 1.1 if ((propertyFlags & MI_FLAG_PROPERTY) == 0)
548 {
549 //Dynamic classes do not have qualifiers, only flags. They don't even mark a property as being a property!
550
551 //If this is a dynanic instance and this is property is an embedded instance then we need to fabricate a EmbeddedObject qualifier otherwise
552 //deserialization will think it is a string
553 if ((propertyType&~MI_ARRAY) == MI_INSTANCE)
554 {
555 WriteBuffer_EmbeddedPropertyQualifier(clientBuffer, clientBufferLength, clientBufferNeeded, propertyReferenceClass, result);
556 }
557
558 WriteBuffer_MiFlagQualifiers(clientBuffer, clientBufferLength, clientBufferNeeded, propertyFlags, result);
559 }
560 else
561 {
562 WriteBuffer_MiParamPropertyQualifierSet(clientBuffer, clientBufferLength, clientBufferNeeded, &propertyQualifierSet, propertyFlags, isInheritedElement, ((propertyType&~MI_ARRAY) == MI_INSTANCE), propertyReferenceClass, result);
563 }
564 }
565
566 /* Values and closing element */
567 if (propertyType & MI_ARRAY)
568 krisbash 1.1 {
569 if (propertyType == MI_REFERENCEA)
570 {
571 //Property arrays are not supported in CIM or in serialization.
572 //This is a hard error overwriting any other error that may be there.
573 *result = MI_RESULT_NOT_SUPPORTED;
574 return;
575 }
576 else
577 {
578 /* VALUE.ARRAY*/
579 if (instanceStart)
580 {
581 #ifdef _MSC_VER
582 #pragma prefast(push)
583 #pragma prefast (disable: 26007)
584 #endif
585 if (propertyValueExists)
586 WriteBuffer_MiArrayField(clientBuffer, clientBufferLength, clientBufferNeeded, propertyType, (MI_ArrayField*)(instanceStart+propertyOffset), escapingDepth, result);
587 #ifdef _MSC_VER
588 #pragma prefast(pop)
589 krisbash 1.1 #endif
590 }
591 else
592 {
593 if (propertyValueExists && ((propertyType & MI_FLAG_NULL) == 0))
594 WriteBuffer_MiValueArray(clientBuffer, clientBufferLength, clientBufferNeeded, propertyType, (MI_Array*)(&propertyValue), SERIALIZE_NO_ESCAPE, result);
595 }
596
597 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</PROPERTY.ARRAY>"), escapingDepth, result);
598 }
599 }
600 else if (propertyType == MI_REFERENCE)
601 {
602 MI_Instance *refValue = NULL;
603 if (instanceStart)
604 {
605 MI_ReferenceField *field = (MI_ReferenceField *)(instanceStart+propertyOffset);
606
607 refValue = field->value;
608
609 }
610 krisbash 1.1 else
611 {
612 if (propertyValueExists)
613 {
614 refValue = propertyValue.instance;
615 }
616 }
617
618 if (refValue)
619 {
620 WriteBuffer_InstanceReference(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, serverName, refValue, escapingDepth, result);
621 }
622 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</PROPERTY.REFERENCE>"), escapingDepth, result);
623 }
624 else
625 {
626 /* VALUE */
627 if (instanceStart)
628 {
629 WriteBuffer_MiTypeField(clientBuffer, clientBufferLength, clientBufferNeeded, propertyType, instanceStart+propertyOffset, escapingDepth, result);
630 }
631 krisbash 1.1 else
632 {
633 if(propertyValueExists)
634 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, propertyType, (MI_Value*)(&propertyValue), MI_TRUE, SERIALIZE_NO_ESCAPE, result);
635 }
636
637 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</PROPERTY>"), escapingDepth, result);
638 }
639 }
640 }
641
642 MI_INLINE void WriteBuffer_NoneEscapedChar(
643 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
644 MI_Uint32 clientBufferLength,
645 _Inout_ MI_Uint32 *clientBufferNeeded,
646 _In_ const MI_Char charToWrite,
647 _Inout_ MI_Result *result)
648 {
649 MI_Uint32 origBufferNeeded = *clientBufferNeeded;
650 (*clientBufferNeeded)+=sizeof(MI_Char);
651 if ((*result==MI_RESULT_OK) && (*clientBufferNeeded <= clientBufferLength))
652 krisbash 1.1 {
653 ((MI_Char*)clientBuffer)[origBufferNeeded/sizeof(MI_Char)] = charToWrite;
654 }
655 else if (*result == MI_RESULT_OK)
656 {
657 //If error has not already been set then set it now
658 *result = MI_RESULT_FAILED;
659 }
660 }
661 static void WriteBuffer_Char(
662 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
663 MI_Uint32 clientBufferLength,
664 _Inout_ MI_Uint32 *clientBufferNeeded,
665 _In_ const MI_Char charToWrite,
666 MI_Uint32 escapingDepth, //0 means no escaping
667 _Inout_ MI_Result *result)
668 {
669 static const struct
670 {
671 const MI_Char* str;
672 size_t len;
673 krisbash 1.1 } _encode[] =
674 {
675 { PAL_T("�"), 4 },
676 { PAL_T(""), 4 },
677 { PAL_T(""), 4 },
678 { PAL_T(""), 4 },
679 { PAL_T(""), 4 },
680 { PAL_T(""), 4 },
681 { PAL_T(""), 4 },
682 { PAL_T(""), 4 },
683 { PAL_T(""), 4 },
684 { PAL_T("	"), 4 },
685 { PAL_T(" "), 5 },
686 { PAL_T(""), 5 },
687 { PAL_T(""), 5 },
688 { PAL_T(" "), 5},
689 { PAL_T(""), 5 },
690 { PAL_T(""), 5 },
691 { PAL_T(""), 5 },
692 { PAL_T(""), 5 },
693 { PAL_T(""), 5 },
694 krisbash 1.1 { PAL_T(""), 5 },
695 { PAL_T(""), 5 },
696 { PAL_T(""), 5 },
697 { PAL_T(""), 5 },
698 { PAL_T(""), 5 },
699 { PAL_T(""), 5 },
700 { PAL_T(""), 5 },
701 { PAL_T(""), 5 },
702 { PAL_T(""), 5 },
703 { PAL_T(""), 5 },
704 { PAL_T(""), 5 },
705 { PAL_T(""), 5 },
706 { PAL_T(""), 5 },
707 { NULL, 0 },
708 { NULL, 0 },
709 { PAL_T("""), 6 },
710 { NULL, 0 },
711 { NULL, 0 },
712 { NULL, 0 },
713 { PAL_T("&"), 5 },
714 { PAL_T("'"), 6 },
715 krisbash 1.1 { NULL, 0 },
716 { NULL, 0 },
717 { NULL, 0 },
718 { NULL, 0 },
719 { NULL, 0 },
720 { NULL, 0 },
721 { NULL, 0 },
722 { NULL, 0 },
723 { NULL, 0 },
724 { NULL, 0 },
725 { NULL, 0 },
726 { NULL, 0 },
727 { NULL, 0 },
728 { NULL, 0 },
729 { NULL, 0 },
730 { NULL, 0 },
731 { NULL, 0 },
732 { NULL, 0 },
733 { NULL, 0 },
734 { NULL, 0 },
735 { PAL_T("<"), 4 },
736 krisbash 1.1 { NULL, 0 },
737 { PAL_T(">"), 4 }
738 };
739
740 if ((escapingDepth == 0) ||
741 (charToWrite > L'>') ||
742 (_encode[(unsigned int)charToWrite].str == NULL))
743 {
744 WriteBuffer_NoneEscapedChar(clientBuffer, clientBufferLength, clientBufferNeeded, charToWrite, result);
745 }
746 else
747 {
748 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded, _encode[(unsigned int)charToWrite].str, _encode[(unsigned int)charToWrite].len, escapingDepth-1, result);
749 }
750 }
751
752 /* Preferred write mechanism as we don't need to Tcslen the buffer to write */
753 static void WriteBuffer_StringWithLength(
754 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
755 MI_Uint32 clientBufferLength,
756 _Inout_ MI_Uint32 *clientBufferNeeded,
757 krisbash 1.1 _In_reads_z_(bufferToWriteLength) const MI_Char *bufferToWrite,
758 MI_Uint32 bufferToWriteLength,
759 MI_Uint32 escapingDepth, //0 or SERIALIZE_NO_ESCAPE means no escaping
760 _Inout_ MI_Result *result)
761 {
762 if (escapingDepth == 0)
763 {
764 MI_Uint32 origBufferNeeded = *clientBufferNeeded;
765 (*clientBufferNeeded) += (bufferToWriteLength * sizeof(MI_Char));
766 if ((*result==MI_RESULT_OK) && (*clientBufferNeeded <= clientBufferLength))
767 {
768 memcpy(clientBuffer + origBufferNeeded, bufferToWrite, bufferToWriteLength * sizeof(MI_Char));
769 }
770 else if (*result == MI_RESULT_OK)
771 {
772 //If error has not already been set then set it now
773 *result = MI_RESULT_FAILED;
774 }
775 }
776 else
777 {
778 krisbash 1.1 MI_Uint32 loop;
779 for (loop = 0; loop != bufferToWriteLength; loop++)
780 {
781 WriteBuffer_Char(clientBuffer, clientBufferLength, clientBufferNeeded, bufferToWrite[loop], escapingDepth, result);
782 }
783 }
784 }
785
786 /* writes the textual version of MI_Type */
787 static void WriteBuffer_MiType(
788 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
789 MI_Uint32 clientBufferLength,
790 _Inout_ MI_Uint32 *clientBufferNeeded,
791 MI_Type type,
792 MI_Uint32 escapingDepth,
793 _Inout_ MI_Result *result)
794 {
795 static struct _mapping { const MI_Char *typeString; MI_Uint32 typeStringLength; } mapping[] =
796 {
797 {PAL_T("boolean"), WCSLEN(PAL_T("boolean")) },
798 {PAL_T("uint8"), WCSLEN(PAL_T("uint8")) },
799 krisbash 1.1 {PAL_T("sint8"), WCSLEN(PAL_T("sint8")) },
800 {PAL_T("uint16"), WCSLEN(PAL_T("uint16")) },
801 {PAL_T("sint16"), WCSLEN(PAL_T("sint16")) },
802 {PAL_T("uint32"), WCSLEN(PAL_T("uint32")) },
803 {PAL_T("sint32"), WCSLEN(PAL_T("sint32")) },
804 {PAL_T("uint64"), WCSLEN(PAL_T("uint64")) },
805 {PAL_T("sint64"), WCSLEN(PAL_T("sint64")) },
806 {PAL_T("real32"), WCSLEN(PAL_T("real32")) },
807 {PAL_T("real64"), WCSLEN(PAL_T("real64")) },
808 {PAL_T("char16"), WCSLEN(PAL_T("char16")) },
809 {PAL_T("datetime"), WCSLEN(PAL_T("datetime")) },
810 {PAL_T("string"), WCSLEN(PAL_T("string")) },
811 {PAL_T("unused"), WCSLEN(PAL_T("unused")) }, /* Reference, not used */
812 {PAL_T("string"), WCSLEN(PAL_T("string")) } /* Instance is encoded as a string */
813 };
814 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" TYPE=\""), escapingDepth, result);
815 if ((type&~MI_ARRAY) >= sizeof(mapping)/sizeof(mapping[0]))
816 {
817 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("unknown"), WCSLEN(PAL_T("unknown")), SERIALIZE_NO_ESCAPE, result);
818 }
819 else
820 krisbash 1.1 {
821 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded, mapping[type&~MI_ARRAY].typeString, mapping[type&~MI_ARRAY].typeStringLength, SERIALIZE_NO_ESCAPE, result);
822 }
823 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), escapingDepth, result);
824 }
825
826 /* writes the textual version of MI_Array based on MI_Type. */
827 static void WriteBuffer_MiValueArray(
828 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
829 MI_Uint32 clientBufferLength,
830 _Inout_ MI_Uint32 *clientBufferNeeded,
831 MI_Type type,
832 _In_ const MI_Array *arrayValue,
833 MI_Uint32 escapingDepth,
834 _Inout_ MI_Result *result)
835 {
836 MI_Uint32 index;
837 MI_Type scalarType = (MI_Type)(type&~MI_ARRAY);
838 char* ptr;
839
840 if (arrayValue == NULL)
841 krisbash 1.1 return;
842
843 ptr = (char*)arrayValue->data;
844
845 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<VALUE.ARRAY>"),escapingDepth, result);
846 for(index = 0; index != arrayValue->size; index++)
847 {
848 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, scalarType, (MI_Value*)ptr, MI_TRUE, escapingDepth, result);
849
850 ptr += Type_SizeOf(scalarType);
851 }
852 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</VALUE.ARRAY>"),escapingDepth, result);
853 }
854
855 /* writes the textual version of MI_Value based on MI_Type. */
856 static void WriteBuffer_MiValue(
857 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
858 MI_Uint32 clientBufferLength,
859 _Inout_ MI_Uint32 *clientBufferNeeded,
860 MI_Type type,
861 _In_opt_ const MI_Value *value,
862 krisbash 1.1 MI_Boolean includeTags,
863 MI_Uint32 escapingDepth,
864 _Inout_ MI_Result *result)
865 {
866 // MI_Char stringbuffer[_CVTBUFSIZE];
867 TChar strBufForUnsignedConversion[21];
868 TChar strBufForSignedConversion[64];
869 const TChar *convertedBuffer = NULL;
870 TChar strBufForDatetimeConversion[26];
871 size_t convertedSize = 0;
872
873 if (value == NULL)
874 return;
875
876 strBufForSignedConversion[0] = PAL_T('\0');
877 if (includeTags)
878 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<VALUE>"), escapingDepth, result);
879
880 switch(type)
881 {
882 case MI_BOOLEAN:
883 krisbash 1.1 {
884 MI_Boolean boolValue = value->boolean;
885 if (boolValue)
886 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("true"), SERIALIZE_NO_ESCAPE, result);
887 else
888 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("false"), SERIALIZE_NO_ESCAPE, result);
889 break;
890 }
891 case MI_UINT8:
892 Uint64ToZStr(strBufForUnsignedConversion, value->uint8, &convertedBuffer, &convertedSize);
893 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
894 convertedBuffer, convertedSize,
895 SERIALIZE_NO_ESCAPE, result);
896 break;
897 case MI_SINT8:
898 Sint64ToZStr(strBufForSignedConversion, value->sint8, &convertedBuffer, &convertedSize);
899 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
900 convertedBuffer, convertedSize,
901 SERIALIZE_NO_ESCAPE, result);
902 break;
903 case MI_UINT16:
904 krisbash 1.1 Uint64ToZStr(strBufForUnsignedConversion, value->uint16, &convertedBuffer, &convertedSize);
905 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
906 convertedBuffer, convertedSize,
907 SERIALIZE_NO_ESCAPE, result);
908 break;
909 case MI_SINT16:
910 Sint64ToZStr(strBufForSignedConversion, value->sint16, &convertedBuffer, &convertedSize);
911 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
912 convertedBuffer, convertedSize,
913 SERIALIZE_NO_ESCAPE, result);
914 break;
915 case MI_UINT32:
916 Uint64ToZStr(strBufForUnsignedConversion, value->uint32, &convertedBuffer, &convertedSize);
917 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
918 convertedBuffer, convertedSize,
919 SERIALIZE_NO_ESCAPE, result);
920 break;
921 case MI_SINT32:
922 Sint64ToZStr(strBufForSignedConversion, value->sint32, &convertedBuffer, &convertedSize);
923 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
924 convertedBuffer, convertedSize,
925 krisbash 1.1 SERIALIZE_NO_ESCAPE, result);
926 break;
927 case MI_UINT64:
928 Uint64ToZStr(strBufForUnsignedConversion, value->uint64, &convertedBuffer, &convertedSize);
929 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
930 convertedBuffer, convertedSize,
931 SERIALIZE_NO_ESCAPE, result);
932 break;
933 case MI_SINT64:
934 Sint64ToZStr(strBufForSignedConversion, value->sint64, &convertedBuffer, &convertedSize);
935 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
936 convertedBuffer, convertedSize,
937 SERIALIZE_NO_ESCAPE, result);
938 break;
939 case MI_REAL32:
940 {
941 #if defined(_MSC_VER)
942 unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);
943 #endif
944 Stprintf(strBufForSignedConversion, MI_COUNT(strBufForSignedConversion), PAL_T("%.7e"), (double)value->real32);
945 #if defined(_MSC_VER)
946 krisbash 1.1 _set_output_format(old_exponent_format);
947 #endif
948 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, strBufForSignedConversion, SERIALIZE_NO_ESCAPE, result);
949 break;
950 }
951 case MI_REAL64:
952 {
953 #if defined(_MSC_VER)
954 unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);
955 #endif
956 Stprintf(strBufForSignedConversion, MI_COUNT(strBufForSignedConversion), PAL_T("%.16e"), (double)value->real64);
957
958 #if defined(_MSC_VER)
959 _set_output_format(old_exponent_format);
960 #endif
961 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, strBufForSignedConversion, SERIALIZE_NO_ESCAPE, result);
962 break;
963 }
964 case MI_CHAR16:
965 // We decided to encode the MI_Char16 as number itself since if we do not then we have to encode this differently when the MI_Char is char as opposed to when it is wchar_t
966 // OMI instance serialization also uses the same logic so this makes it consistent with that
967 krisbash 1.1 // WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded, (const MI_Char *)&value->char16, 1, escapingDepth+1, result);
968 Uint64ToZStr(strBufForUnsignedConversion, value->char16, &convertedBuffer, &convertedSize);
969
970 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
971 convertedBuffer, convertedSize,
972 SERIALIZE_NO_ESCAPE, result);
973 break;
974 case MI_DATETIME:
975 {
976 const MI_Datetime* p = (const MI_Datetime*)value;
977
978 DatetimeToStr(p, strBufForDatetimeConversion);
979
980 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, strBufForDatetimeConversion, SERIALIZE_NO_ESCAPE, result);
981
982 break;
983 }
984 case MI_STRING:
985 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, value->string, escapingDepth+1, result);
986 break;
987 //case MI_REFERENCE: /* Other code paths handle this */
988 krisbash 1.1 // break;
989 case MI_INSTANCE:
990 WriteBuffer_Instance(clientBuffer, clientBufferLength, clientBufferNeeded, (MI_Instance*)value->instance, escapingDepth+1, result);
991
992 break;
993 default:
994 *result = MI_RESULT_FAILED;
995 }
996 if (includeTags)
997 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</VALUE>"), escapingDepth, result);
998 }
999
1000 static struct _FlagQualifiers
1001 {
1002 MI_Uint32 flag;
1003 const MI_Char *name;
1004
1005 } sFlagQualifiers[] =
1006 {
1007 { MI_FLAG_KEY, PAL_T("key") },
1008 { MI_FLAG_REQUIRED, PAL_T("required") },
1009 krisbash 1.1 { MI_FLAG_STATIC, PAL_T("static") },
1010 { MI_FLAG_EXPENSIVE, PAL_T("expensive") },
1011 { MI_FLAG_READONLY, PAL_T("read") },
1012 { MI_FLAG_IN, PAL_T("in") },
1013 { MI_FLAG_OUT, PAL_T("out") },
1014 { MI_FLAG_ABSTRACT, PAL_T("abstract") },
1015 { MI_FLAG_TERMINAL, PAL_T("terminal") },
1016 { MI_FLAG_ASSOCIATION, PAL_T("association") },
1017 { MI_FLAG_INDICATION, PAL_T("indication") },
1018 // { MI_FLAG_STREAM, PAL_T("stream") },
1019 };
1020
1021 static MI_Uint32 sFlagQualifierCount = sizeof(sFlagQualifiers)/sizeof(sFlagQualifiers[0]);
1022
1023 /* writes the textual version of MI_Qualifier flags. */
1024 static void WriteBuffer_MiFlagQualifiers(
1025 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1026 MI_Uint32 clientBufferLength,
1027 _Inout_ MI_Uint32 *clientBufferNeeded,
1028 MI_Uint32 flagsToSerializeAsQualifiers,
1029 _Inout_ MI_Result *result)
1030 krisbash 1.1 {
1031 MI_Value value;
1032 MI_Uint32 index;
1033
1034 value.boolean = MI_TRUE;
1035
1036 for (index = 0; index != sFlagQualifierCount; index++)
1037 {
1038 if (flagsToSerializeAsQualifiers & sFlagQualifiers[index].flag)
1039 {
1040 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<QUALIFIER"), SERIALIZE_NO_ESCAPE, result);
1041
1042 /* %CIMName; */
1043 WriteBuffer_CimName(clientBuffer, clientBufferLength, clientBufferNeeded, sFlagQualifiers[index].name, SERIALIZE_NO_ESCAPE, result);
1044
1045 /* %CIMType; */
1046 WriteBuffer_MiType(clientBuffer, clientBufferLength, clientBufferNeeded, MI_BOOLEAN, SERIALIZE_NO_ESCAPE, result);
1047
1048
1049 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), SERIALIZE_NO_ESCAPE, result);
1050
1051 krisbash 1.1 /* VALUE */
1052 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, MI_BOOLEAN, &value, MI_TRUE, SERIALIZE_NO_ESCAPE, result);
1053
1054 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</QUALIFIER>"), SERIALIZE_NO_ESCAPE, result);
1055 }
1056 }
1057 }
1058
1059 // this function looks up the qualifiername in the sQualifierFlags list and
1060 // resets the corresponding flag from the given flags bitmask.
1061 // this could use a hash table lookup but not adding complexity
1062 // since it is a very small table so the lookup will be constant time
1063 static void ResetFlagForQualifier(_Inout_ MI_Uint32 *flags, const MI_Char *qualifierName)
1064 {
1065 MI_Uint32 index;
1066
1067 // assumption is that flags has to be non-null
1068 if(flags == NULL)
1069 {
1070 return;
1071 }
1072 krisbash 1.1
1073 for (index = 0; index != sFlagQualifierCount; index++)
1074 {
1075 if(Tcscasecmp(qualifierName, sFlagQualifiers[index].name) == 0)
1076 {
1077 *flags = *flags & (~(sFlagQualifiers[index].flag));
1078 break;
1079 }
1080 }
1081 }
1082
1083 static void WriteBuffer_EmbeddedPropertyQualifier(
1084 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1085 MI_Uint32 clientBufferLength,
1086 _Inout_ MI_Uint32 *clientBufferNeeded,
1087 _In_opt_ const MI_Char *referenceClassForEmbeddedProperty,
1088 _Inout_ MI_Result *result)
1089 {
1090 MI_Type type;
1091 MI_Value value;
1092 const MI_Char *qualifierName = NULL;
1093 krisbash 1.1
1094 if(referenceClassForEmbeddedProperty == NULL)
1095 {
1096 type = MI_BOOLEAN;
1097 value.boolean = MI_TRUE;
1098 qualifierName = PAL_T("EmbeddedObject");
1099 }
1100 else
1101 {
1102 type = MI_STRING;
1103 value.string = (MI_Char *)referenceClassForEmbeddedProperty;
1104 qualifierName = PAL_T("EmbeddedInstance");
1105 }
1106
1107 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<QUALIFIER"), SERIALIZE_NO_ESCAPE, result);
1108
1109 /* %CIMName; */
1110 WriteBuffer_CimName(clientBuffer, clientBufferLength, clientBufferNeeded, qualifierName, SERIALIZE_NO_ESCAPE, result);
1111
1112 /* %CIMType; */
1113 WriteBuffer_MiType(clientBuffer, clientBufferLength, clientBufferNeeded, type, SERIALIZE_NO_ESCAPE, result);
1114 krisbash 1.1
1115 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), SERIALIZE_NO_ESCAPE, result);
1116
1117 /* VALUE -- embedded instance class name or true for embedded object */
1118 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, type, &value, MI_TRUE, SERIALIZE_NO_ESCAPE, result);
1119
1120 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</QUALIFIER>"), SERIALIZE_NO_ESCAPE, result);
1121
1122 }
1123
1124 static void WriteBuffer_MiQualifierSet(
1125 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1126 MI_Uint32 clientBufferLength,
1127 _Inout_ MI_Uint32 *clientBufferNeeded,
1128 _In_ const MI_QualifierSet *qualifierSet,
1129 MI_Uint32 flagsToSerializeAsQualifiers,
1130 MI_Boolean isQualOnInheritedElement,
1131 _Inout_ MI_Result *result)
1132 {
1133 WriteBuffer_MiParamPropertyQualifierSet(clientBuffer, clientBufferLength, clientBufferNeeded, qualifierSet, flagsToSerializeAsQualifiers, isQualOnInheritedElement, MI_FALSE, NULL, result);
1134 }
1135 krisbash 1.1
1136 static void WriteBuffer_MiParamPropertyQualifierSet(
1137 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1138 MI_Uint32 clientBufferLength,
1139 _Inout_ MI_Uint32 *clientBufferNeeded,
1140 _In_ const MI_QualifierSet *qualifierSet,
1141 MI_Uint32 flagsToSerializeAsQualifiers,
1142 MI_Boolean isQualOnInheritedElement,
1143 MI_Boolean isEmbeddedProperty,
1144 _In_opt_ const MI_Char *referenceClassForEmbeddedProperty,
1145 _Inout_ MI_Result *result)
1146 {
1147 MI_Uint32 index;
1148 MI_Uint32 qualifierCount = 0;
1149 const MI_Char *qualifierName = NULL;
1150 MI_Type qualifierType;
1151 MI_Uint32 qualifierFlags;
1152 MI_Value qualifierValue;
1153 MI_Boolean embeddedPropertyQualifierSpecified = 0;
1154
1155 if(qualifierSet)
1156 krisbash 1.1 {
1157 GetQualifierSetFt(qualifierSet)->GetQualifierCount(qualifierSet, &qualifierCount);
1158 }
1159
1160 for (index = 0; index != qualifierCount; index++)
1161 {
1162 GetQualifierSetFt(qualifierSet)->GetQualifierAt(qualifierSet, index, &qualifierName, &qualifierType, &qualifierFlags, &qualifierValue);
1163
1164 // Restricted qualifier should not be sent on inherited elements
1165 if (isQualOnInheritedElement && (qualifierFlags & MI_FLAG_RESTRICTED))
1166 continue;
1167
1168 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<QUALIFIER"), SERIALIZE_NO_ESCAPE, result);
1169
1170 /* %CIMName; */
1171 WriteBuffer_CimName(clientBuffer, clientBufferLength, clientBufferNeeded, qualifierName, SERIALIZE_NO_ESCAPE, result);
1172
1173 ResetFlagForQualifier(&flagsToSerializeAsQualifiers, qualifierName);
1174
1175 // for embeddedProperties, we will see if an explicit EmbeddedObject/EmbeddedInstance qualifier was specified, if it was not
1176 // we will fabricate it here after the end of the loop
1177 krisbash 1.1 if(isEmbeddedProperty)
1178 {
1179 if(referenceClassForEmbeddedProperty == NULL)
1180 {
1181 if(Tcscasecmp(qualifierName, PAL_T("EmbeddedObject")) == 0)
1182 {
1183 embeddedPropertyQualifierSpecified = 1;
1184 }
1185 }
1186 else
1187 {
1188 if(Tcscasecmp(qualifierName, PAL_T("EmbeddedInstance")) == 0)
1189 {
1190 embeddedPropertyQualifierSpecified = 1;
1191 }
1192 }
1193 }
1194
1195 /* %CIMType; */
1196 WriteBuffer_MiType(clientBuffer, clientBufferLength, clientBufferNeeded, qualifierType, SERIALIZE_NO_ESCAPE, result);
1197
1198 krisbash 1.1 /* %Propagated; TODO*/
1199
1200 /* %QualifierFlavor; */
1201 /* OVERRIDABLE defaults to TRUE so only set if FALSE */
1202 if (qualifierFlags & MI_FLAG_DISABLEOVERRIDE)
1203 {
1204 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" OVERRIDABLE=\"false\""), SERIALIZE_NO_ESCAPE, result);
1205 }
1206 /* TOSUBCLASS defaults to TRUE, so only add if not set */
1207 if (qualifierFlags & MI_FLAG_RESTRICTED)
1208 {
1209 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" TOSUBCLASS=\"false\""), SERIALIZE_NO_ESCAPE, result);
1210 }
1211 if (qualifierFlags & MI_FLAG_TRANSLATABLE)
1212 {
1213 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" TRANSLATABLE=\"true\""), SERIALIZE_NO_ESCAPE, result);
1214 }
1215
1216 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), SERIALIZE_NO_ESCAPE, result);
1217
1218 /* VALUE | VALUE.ARRAY */
1219 krisbash 1.1 if (qualifierType & MI_ARRAY)
1220 {
1221 WriteBuffer_MiValueArray(clientBuffer, clientBufferLength, clientBufferNeeded, (MI_Type)qualifierType, (MI_Array*)(&qualifierValue), SERIALIZE_NO_ESCAPE, result);
1222 }
1223 else
1224 {
1225 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, (MI_Type)qualifierType, &qualifierValue, MI_TRUE, SERIALIZE_NO_ESCAPE, result);
1226 }
1227
1228 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</QUALIFIER>"), SERIALIZE_NO_ESCAPE, result);
1229 }
1230
1231 // code to fabricate embedded qualifier
1232 if(isEmbeddedProperty && !embeddedPropertyQualifierSpecified)
1233 {
1234 WriteBuffer_EmbeddedPropertyQualifier(clientBuffer, clientBufferLength, clientBufferNeeded, referenceClassForEmbeddedProperty, result);
1235 }
1236
1237 WriteBuffer_MiFlagQualifiers(clientBuffer, clientBufferLength, clientBufferNeeded, flagsToSerializeAsQualifiers, result);
1238 }
1239
1240 krisbash 1.1
1241 /* writes the textual version of %CIMName. (name="name") */
1242 static void WriteBuffer_CimName(
1243 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1244 MI_Uint32 clientBufferLength,
1245 _Inout_ MI_Uint32 *clientBufferNeeded,
1246 _In_z_ const MI_Char* name,
1247 MI_Uint32 escapingDepth,
1248 _Inout_ MI_Result *result)
1249 {
1250 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(" NAME=\""), escapingDepth, result);
1251 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, name, escapingDepth, result);
1252 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\""), escapingDepth, result);
1253 }
1254
1255 static void WriteBuffer_Uint32(
1256 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1257 MI_Uint32 clientBufferLength,
1258 _Inout_ MI_Uint32 *clientBufferNeeded,
1259 MI_Uint32 number,
1260 _Inout_ MI_Result *result)
1261 krisbash 1.1 {
1262 // MI_Char stringbuffer[_CVTBUFSIZE];
1263 TChar strBufForUnsignedConversion[21];
1264 size_t convertedSize = 0;
1265 const TChar *convertedBuffer = NULL;
1266
1267 Uint64ToZStr(strBufForUnsignedConversion, number, &convertedBuffer, &convertedSize);
1268
1269 WriteBuffer_StringWithLength(clientBuffer, clientBufferLength, clientBufferNeeded,
1270 convertedBuffer, convertedSize,
1271 SERIALIZE_NO_ESCAPE, result);
1272 }
1273
1274 MI_INLINE MI_Boolean _Exists(MI_Type type, const void* field)
1275 {
1276 return *((MI_Boolean*)((char*)field + Type_SizeOf(type)));
1277 }
1278
1279 static void WriteBuffer_MiTypeField(
1280 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1281 MI_Uint32 clientBufferLength,
1282 krisbash 1.1 _Inout_ MI_Uint32 *clientBufferNeeded,
1283 MI_Type type,
1284 _In_ const char *fieldValue,
1285 MI_Uint32 escapingDepth,
1286 _Inout_ MI_Result *result)
1287 {
1288 if (_Exists(type, fieldValue))
1289 {
1290 #ifdef _MSC_VER
1291 #pragma prefast(push)
1292 #pragma prefast (disable: 26007)
1293 #endif
1294 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, type, (MI_Value*)fieldValue, MI_TRUE, escapingDepth, result);
1295 #ifdef _MSC_VER
1296 #pragma prefast(pop)
1297 #endif
1298 }
1299 }
1300
1301 static void WriteBuffer_MiArrayField(
1302 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1303 krisbash 1.1 MI_Uint32 clientBufferLength,
1304 _Inout_ MI_Uint32 *clientBufferNeeded,
1305 MI_Type type,
1306 _In_ MI_ArrayField *arrayField,
1307 MI_Uint32 escapingDepth,
1308 _Inout_ MI_Result *result
1309 )
1310 {
1311 MI_Uint32 index;
1312 MI_Type scalarType = (MI_Type)(type&~MI_ARRAY);
1313 char* ptr = (char*)arrayField->value.data;
1314
1315 if (_Exists(type, arrayField))
1316 {
1317 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<VALUE.ARRAY>"), escapingDepth, result);
1318 if (ptr)
1319 {
1320 for(index = 0; index != arrayField->value.size; index++)
1321 {
1322 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, scalarType, (MI_Value*)ptr, MI_TRUE, escapingDepth, result);
1323
1324 krisbash 1.1 ptr += Type_SizeOf(scalarType);
1325 }
1326 }
1327 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</VALUE.ARRAY>"), escapingDepth, result);
1328 }
1329 }
1330
1331 static void WriteBuffer_LOCALNAMESPACEPATH_Internal(
1332 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1333 MI_Uint32 clientBufferLength,
1334 _Inout_ MI_Uint32 *clientBufferNeeded,
1335 _In_z_ const MI_Char *namespaceName,
1336 MI_Uint32 escapingDepth,
1337 _Inout_ MI_Result *result)
1338 {
1339 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<NAMESPACE NAME=\""), escapingDepth, result);
1340 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, escapingDepth, result);
1341 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\"/>"), escapingDepth, result);
1342 }
1343
1344 static void WriteBuffer_LOCALNAMESPACEPATH(
1345 krisbash 1.1 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1346 MI_Uint32 clientBufferLength,
1347 _Inout_ MI_Uint32 *clientBufferNeeded,
1348 _In_z_ const MI_Char *namespaceName,
1349 MI_Uint32 escapingDepth,
1350 _Inout_ MI_Result *result)
1351 {
1352 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<LOCALNAMESPACEPATH>"), escapingDepth, result);
1353 {
1354 MI_Uint32 uNamespaceLength = Tcslen(namespaceName) + 1;
1355 // add fault sim shim for all malloc calls in omi
1356 MI_Char * tNamespace = (MI_Char *)PAL_Malloc(sizeof(MI_Char)*uNamespaceLength);
1357 MI_Char * pCurrentNamespace;
1358 const MI_Char * pSearch;
1359 if (tNamespace == NULL)
1360 {
1361 *result = MI_RESULT_SERVER_LIMITS_EXCEEDED;
1362 return;
1363 }
1364 pCurrentNamespace = tNamespace;
1365 pSearch = namespaceName;
1366 krisbash 1.1 // suppose namespaceName could be "a\\b/c\\d//e"
1367 while(*pSearch != L'\0')
1368 {
1369 if (*pSearch == L'/' || *pSearch == L'\\')
1370 {
1371 if (pCurrentNamespace != tNamespace)
1372 {
1373 #ifdef _MSC_VER
1374 #pragma prefast(push)
1375 #pragma prefast (disable: 26001)
1376 #endif
1377 // write terminator
1378 *pCurrentNamespace = L'\0';
1379 #ifdef _MSC_VER
1380 #pragma prefast(pop)
1381 #endif
1382 // the namespace part is not empty, write this part to local NAMESPACE
1383 WriteBuffer_LOCALNAMESPACEPATH_Internal(clientBuffer, clientBufferLength, clientBufferNeeded, tNamespace, escapingDepth, result);
1384 // reset pCurrentNamespace
1385 pCurrentNamespace = tNamespace;
1386 }
1387 krisbash 1.1 }
1388 else
1389 {
1390 *pCurrentNamespace = *pSearch;
1391 pCurrentNamespace++;
1392 }
1393 pSearch ++;
1394 }
1395 if (pCurrentNamespace != tNamespace)
1396 {
1397 // write terminator
1398 *pCurrentNamespace = L'\0';
1399 // the namespace part is not empty, write this part to local NAMESPACE
1400 WriteBuffer_LOCALNAMESPACEPATH_Internal(clientBuffer, clientBufferLength, clientBufferNeeded, tNamespace, escapingDepth, result);
1401 }
1402 PAL_Free(tNamespace);
1403 }
1404 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</LOCALNAMESPACEPATH>"), escapingDepth, result);
1405 }
1406 static void WriteBuffer_NAMESPACEPATH(
1407 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1408 krisbash 1.1 MI_Uint32 clientBufferLength,
1409 _Inout_ MI_Uint32 *clientBufferNeeded,
1410 _In_z_ const MI_Char *namespaceName,
1411 _In_z_ const MI_Char *serverName,
1412 MI_Uint32 escapingDepth,
1413 _Inout_ MI_Result *result)
1414 {
1415 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<NAMESPACEPATH><HOST>"), escapingDepth, result);
1416 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, serverName, escapingDepth, result);
1417 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</HOST>"), escapingDepth, result);
1418 WriteBuffer_LOCALNAMESPACEPATH(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, escapingDepth, result);
1419 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</NAMESPACEPATH>"), escapingDepth, result);
1420 }
1421
1422 static void WriteBuffer_INSTANCENAME_single(
1423 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1424 MI_Uint32 clientBufferLength,
1425 _Inout_ MI_Uint32 *clientBufferNeeded,
1426 _In_ const MI_Instance *refValue,
1427 MI_Type type,
1428 _In_ MI_Value *value,
1429 krisbash 1.1 MI_Uint32 escapingDepth,
1430 _Inout_ MI_Result *result)
1431 {
1432 if (type == MI_REFERENCE)
1433 {
1434 const MI_Char *namespaceName = NULL;
1435 const MI_Char *serverName = NULL;
1436 if ((value->instance->nameSpace && (refValue->nameSpace == NULL)) ||
1437 (refValue->nameSpace && value->instance->nameSpace && (Tcscasecmp(refValue->nameSpace, value->instance->nameSpace) != 0)))
1438 {
1439 namespaceName = value->instance->nameSpace;
1440 }
1441 if ((value->instance->serverName && (refValue->serverName == NULL)) ||
1442 (refValue->serverName && value->instance->serverName && (Tcscasecmp(refValue->serverName, value->instance->serverName) != 0)))
1443 {
1444 serverName = value->instance->serverName;
1445 }
1446 WriteBuffer_InstanceReference(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, serverName, value->reference, escapingDepth, result);
1447 }
1448 else
1449 {
1450 krisbash 1.1 switch(type)
1451 {
1452 case MI_BOOLEAN:
1453 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<KEYVALUE VALUETYPE=\"boolean\""), escapingDepth, result);
1454 break;
1455 case MI_DATETIME:
1456 case MI_STRING:
1457 case MI_CHAR16:
1458 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<KEYVALUE VALUETYPE=\"string\""), escapingDepth, result);
1459 break;
1460 default:
1461 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<KEYVALUE VALUETYPE=\"numeric\""), escapingDepth, result);
1462 break;
1463 }
1464 WriteBuffer_MiType(clientBuffer, clientBufferLength, clientBufferNeeded, (MI_Type)type, escapingDepth, result);
1465
1466 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T(">"), escapingDepth, result);
1467
1468 WriteBuffer_MiValue(clientBuffer, clientBufferLength, clientBufferNeeded, type, value, MI_FALSE, escapingDepth, result);
1469
1470 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</KEYVALUE>"), escapingDepth, result);
1471 krisbash 1.1 }
1472 }
1473 static void WriteBuffer_INSTANCENAME(
1474 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1475 MI_Uint32 clientBufferLength,
1476 _Inout_ MI_Uint32 *clientBufferNeeded,
1477 _In_ const MI_Instance *refValue,
1478 MI_Uint32 escapingDepth,
1479 _Inout_ MI_Result *result)
1480 {
1481 /* Need to count keys to determine if we need to use KEYBINDING [more than 1 key] or (KEYVALUE|VALUE.REFERENCE) [only 1 key] */
1482 MI_Uint32 keyCount = 0;
1483 MI_Uint32 propertyIndex;
1484 MI_Uint32 totalPropertyCount = 0;
1485 MI_Class classOfRefValue = MI_CLASS_NULL;
1486 const MI_Char *classNameOfRefValue = NULL;
1487 MI_Uint32 propertyFlags;
1488
1489 *result = MI_Instance_GetClassExt(refValue, &classOfRefValue);
1490
1491 *result = GetClassExtendedFt(&classOfRefValue)->GetClassName(&classOfRefValue, &classNameOfRefValue);
1492 krisbash 1.1
1493 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<INSTANCENAME CLASSNAME=\""), escapingDepth, result);
1494 if(classNameOfRefValue)
1495 {
1496 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, classNameOfRefValue, escapingDepth, result);
1497 }
1498 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\">"), escapingDepth, result);
1499
1500 GetClassExtendedFt(&classOfRefValue)->GetElementCount(&classOfRefValue, &totalPropertyCount);
1501
1502 for (propertyIndex = 0;propertyIndex != totalPropertyCount; propertyIndex++)
1503 {
1504 GetClassExtendedFt(&classOfRefValue)->GetElementAtExt(&classOfRefValue, propertyIndex, NULL, NULL, NULL,
1505 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &propertyFlags);
1506
1507 if (propertyFlags & MI_FLAG_KEY)
1508 {
1509 keyCount++;
1510 }
1511 }
1512
1513 krisbash 1.1 for (propertyIndex = 0;propertyIndex != totalPropertyCount; propertyIndex++)
1514 {
1515 GetClassExtendedFt(&classOfRefValue)->GetElementAtExt(&classOfRefValue, propertyIndex, NULL, NULL, NULL,
1516 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &propertyFlags);
1517
1518 if (propertyFlags & MI_FLAG_KEY)
1519 {
1520 const MI_Char *name;
1521 MI_Value value;
1522 MI_Type type;
1523 MI_Uint32 flags;
1524 MI_Result tmpResult = MI_Instance_GetElementAt(refValue, propertyIndex, &name, &value, &type, &flags);
1525 if (tmpResult != MI_RESULT_OK)
1526 {
1527 *result = tmpResult;
1528 return;
1529 }
1530
1531 if (keyCount == 1)
1532 {
1533 WriteBuffer_INSTANCENAME_single(clientBuffer, clientBufferLength, clientBufferNeeded, refValue, type, &value, escapingDepth, result);
1534 krisbash 1.1 }
1535 else
1536 {
1537 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<KEYBINDING NAME=\""), escapingDepth, result);
1538 WriteBuffer_String(clientBuffer, clientBufferLength, clientBufferNeeded, name, escapingDepth, result);
1539 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("\">"), escapingDepth, result);
1540 WriteBuffer_INSTANCENAME_single(clientBuffer, clientBufferLength, clientBufferNeeded, refValue, type, &value, escapingDepth, result);
1541 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</KEYBINDING>"), escapingDepth, result);
1542 }
1543 }
1544 }
1545 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</INSTANCENAME>"), escapingDepth, result);
1546 }
1547
1548 static void WriteBuffer_LOCALINSTANCEPATH(
1549 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1550 MI_Uint32 clientBufferLength,
1551 _Inout_ MI_Uint32 *clientBufferNeeded,
1552 _In_z_ const MI_Char *namespaceName,
1553 _In_ const MI_Instance *refValue,
1554 MI_Uint32 escapingDepth,
1555 krisbash 1.1 _Inout_ MI_Result *result)
1556 {
1557 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<LOCALINSTANCEPATH>"), escapingDepth, result);
1558 WriteBuffer_LOCALNAMESPACEPATH(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, escapingDepth, result);
1559 WriteBuffer_INSTANCENAME(clientBuffer, clientBufferLength, clientBufferNeeded, refValue, escapingDepth, result);
1560 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</LOCALINSTANCEPATH>"), escapingDepth, result);
1561 }
1562
1563 static void WriteBuffer_INSTANCEPATH(
1564 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1565 MI_Uint32 clientBufferLength,
1566 _Inout_ MI_Uint32 *clientBufferNeeded,
1567 _In_z_ const MI_Char *namespaceName,
1568 _In_z_ const MI_Char *serverName,
1569 _In_ const MI_Instance *refValue,
1570 MI_Uint32 escapingDepth,
1571 _Inout_ MI_Result *result)
1572 {
1573 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<INSTANCEPATH>"), escapingDepth, result);
1574 WriteBuffer_NAMESPACEPATH(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, serverName, escapingDepth, result);
1575 WriteBuffer_INSTANCENAME(clientBuffer, clientBufferLength, clientBufferNeeded, refValue, escapingDepth, result);
1576 krisbash 1.1 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</INSTANCEPATH>"), escapingDepth, result);
1577 }
1578 static void WriteBuffer_InstanceReference(
1579 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1580 MI_Uint32 clientBufferLength,
1581 _Inout_ MI_Uint32 *clientBufferNeeded,
1582 _In_opt_z_ const MI_Char *_namespaceName,
1583 _In_opt_z_ const MI_Char *_serverName,
1584 _In_ const MI_Instance *refInstance_,
1585 MI_Uint32 escapingDepth,
1586 _Inout_ MI_Result *result)
1587 {
1588 const MI_Char *namespaceName = NULL;
1589 const MI_Char *serverName = NULL;
1590 // No one is using OSC_Instance structure inside OMI;
1591 // so I am assuming all instances here are going to be MI_Instances
1592 // so getting rid of this OSC_Instance from the reused code and replacing it with MI_Instance
1593 // in the future if someone adds OSC_Instance in OMI then add this back
1594 // MI_Instance *refInstance = (MI_Instance*)(((OSC_Instance*)refInstance_)->self); //In case this is dynamic instance point to the real one, otherwise it points to ourself!
1595 const MI_Instance *refInstance = refInstance_;
1596
1597 krisbash 1.1 if ((_namespaceName && refInstance->nameSpace && (Tcscasecmp(_namespaceName, refInstance->nameSpace)!=0)) ||
1598 (!_namespaceName && refInstance->nameSpace))
1599 {
1600 namespaceName = refInstance->nameSpace;
1601 }
1602 if ((_serverName && refInstance->serverName && (Tcscasecmp(_serverName, refInstance->serverName)!=0)) ||
1603 (!_serverName && refInstance->serverName))
1604 {
1605 serverName = refInstance->serverName;
1606 }
1607
1608 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("<VALUE.REFERENCE>"), escapingDepth, result);
1609 if (serverName && namespaceName)
1610 {
1611 WriteBuffer_INSTANCEPATH(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, serverName, refInstance, escapingDepth, result);
1612 }
1613 else if (namespaceName)
1614 {
1615 WriteBuffer_LOCALINSTANCEPATH(clientBuffer, clientBufferLength, clientBufferNeeded, namespaceName, refInstance, escapingDepth, result);
1616 }
1617 else
1618 krisbash 1.1 {
1619 WriteBuffer_INSTANCENAME(clientBuffer, clientBufferLength, clientBufferNeeded, refInstance, escapingDepth, result);
1620 }
1621 WriteBuffer_StringLiteral(clientBuffer, clientBufferLength, clientBufferNeeded, PAL_T("</VALUE.REFERENCE>"), escapingDepth, result);
1622 }
1623
1624 /* Serialize class api; assumes the MI_Class is setup with right function table using Class_Construct*/
1625 MI_Result MI_CALL XmlSerializer_SerializeClass(
1626 _Inout_ MI_Serializer *serializer,
1627 MI_Uint32 flags,
1628 _In_ const MI_Class *classObject,
1629 _Out_writes_bytes_(clientBufferLength) MI_Uint8 *clientBuffer,
1630 MI_Uint32 clientBufferLength,
1631 _Inout_ MI_Uint32 *clientBufferNeeded)
1632 {
1633 MI_Result result = MI_RESULT_OK;
1634
1635 MI_Uint32 validFlags = MI_SERIALIZER_FLAGS_CLASS_DEEP | MI_SERIALIZER_FLAGS_INCLUDE_CLASS_ORIGIN |
1636 MI_SERIALIZER_FLAGS_INCLUDE_INHERITANCE_HIERARCHY |
1637 MI_SERIALIZER_FLAGS_INCLUDE_INHERITED_ELEMENTS |
1638 MI_SERIALIZER_FLAGS_INCLUDE_QUALIFIERS;
1639 krisbash 1.1
1640 if (((flags != 0) && (flags & ~validFlags)) ||
1641 (classObject == NULL) || (clientBufferNeeded == NULL))
1642 {
1643 return MI_RESULT_INVALID_PARAMETER;
1644 }
1645
1646 *clientBufferNeeded = 0;
1647
1648 WriteBuffer_SerializeClass(clientBuffer, clientBufferLength, clientBufferNeeded, flags, classObject, classObject->namespaceName, classObject->serverName, &result);
1649
1650 return result;
1651 }
|