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 krisbash 1.4 #include <pal/strings.h>
26 #include <pal/format.h>
|
27 mike 1.1 #include <base/messages.h>
|
28 krisbash 1.4 #include <base/Strand.h>
|
29 mike 1.1 #include <base/log.h>
30 #include <base/paths.h>
|
31 krisbash 1.4 #include <pal/hashmap.h>
32 #include <base/naming.h>
|
33 mike 1.1 #include <wql/wql.h>
34 #include "disp.h"
|
35 krisbash 1.4 #include <omi_error/errorutil.h>
|
36 mike 1.1
|
37 krisbash 1.4 /*
38 **==============================================================================
39 */
40
41 #define DISPENUMPARENT_STRANDAUX_ENUMDONE 0
42
43 STRAND_DEBUGNAME1( DispEnumParent, EnumDone );
44 STRAND_DEBUGNAME( DispEnumEntry );
|
45 mike 1.1
46 /*
47 **==============================================================================
48 **
|
49 mike 1.2 ** ClassName hash implementation
50 **
51 **==============================================================================
52 */
53
54 typedef struct _ClassNameBucket /* derives from HashBucket */
55 {
56 struct _ClassNameBucket* next;
|
57 krisbash 1.4 ZChar* key;
|
58 mike 1.2 }
59 ClassNameBucket;
60
61 static size_t ClassNameHash(
62 const HashBucket* bucket_)
63 {
64 /* Note: this algorithm has a poor distribution */
65 ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
66 size_t h = 0;
|
67 krisbash 1.4 ZChar* key = bucket->key;
|
68 mike 1.2
69 while (*key)
70 {
71 h += 5 * *key++;
72 }
73
74 return h;
75 }
76
77 static int ClassNameEqual(
78 const HashBucket* bucket1_,
79 const HashBucket* bucket2_)
80 {
81 ClassNameBucket* bucket1 = (ClassNameBucket*)bucket1_;
82 ClassNameBucket* bucket2 = (ClassNameBucket*)bucket2_;
|
83 krisbash 1.4 return Tcscasecmp(bucket1->key, bucket2->key) == 0;
|
84 mike 1.2 }
85
86 static void ClassNameRelease(
87 HashBucket* bucket_)
88 {
89 ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
90
|
91 krisbash 1.4 PAL_Free(bucket->key);
92 PAL_Free(bucket);
|
93 mike 1.2 }
94
95 /*
96 **==============================================================================
97 **
|
98 krisbash 1.4 ** Local definitions
|
99 mike 1.1 **
100 **==============================================================================
101 */
102
|
103 krisbash 1.4 typedef struct _DispEnumParent
104 {
105 StrandMany strand;
106 Disp* disp;
107 RequestMsg* baseRequest;
108 MI_Result result;
109 MI_Boolean done;
110 }
111 DispEnumParent;
112
113 typedef struct _EnumEntry EnumEntry;
114
115 struct _EnumEntry
116 {
117 StrandEntry strand;
118 const ZChar* className;
119 EnumEntry* next; // Links the entries that are about to be dispatched
120 // We cannot use list on StrandMany as that one can get modify in the meantime
121 // as the interactions are being dinamically closed themselves
122 // (that is why that list requires to be in the strand to use it)
123 };
124 krisbash 1.4
125 MI_INLINE void _DispEnumParent_Delete(
126 _In_ DispEnumParent* self)
127 {
128 trace_DispDeleteInteraction(self);
129 Message_Release( &self->baseRequest->base );
130 StrandMany_Delete(&self->strand);
131 }
132
133 // interaction is already opened, we can have left the Strand or not indicated by leftStrand
134 static void _SendErrorResponse_Opened(
135 _Inout_ InteractionOpenParams* interactionParams,
136 _In_ DispEnumParent* self,
137 _In_ MI_Result r,
138 MI_Boolean leftStrand
139 )
|
140 mike 1.1 {
|
141 krisbash 1.4 PostResultMsg* openResp = PostResultMsg_NewAndSerialize( &self->baseRequest->base, NULL, NULL, MI_RESULT_TYPE_MI, r);
|
142 mike 1.1
|
143 krisbash 1.4 if( openResp )
144 {
145 if( leftStrand )
146 {
147 StrandMany_SchedulePost( &self->strand, &openResp->base );
148 StrandMany_ScheduleClose( &self->strand );
149 }
150 else
151 {
152 Strand_Post( &self->strand.strand, &openResp->base );
153 Strand_Close( &self->strand.strand );
154 Strand_Leave( &self->strand.strand );
155 }
156 PostResultMsg_Release(openResp);
157 }
158 else
159 {
160 // delete the object directly
161 _DispEnumParent_Delete( self );
162
163 interactionParams->msg = NULL; // Null this out since we have already sent an Ack
164 krisbash 1.4 interactionParams->origin= NULL; // Null this out since we have already left origin strand
165 Strand_FailOpenWithResult(interactionParams, r, PostResultMsg_NewAndSerialize);
166 }
167 }
|
168 mike 1.1
|
169 krisbash 1.4 static void _DispEnumParent__SendLastResponse(
170 _In_ DispEnumParent* interaction
171 )
172 {
173 PostResultMsg* resp;
|
174 mike 1.1
|
175 krisbash 1.4 resp = PostResultMsg_NewAndSerialize(&interaction->baseRequest->base, NULL, NULL, MI_RESULT_TYPE_MI, interaction->result);
176 if( resp )
177 {
178 Strand_Post( &interaction->strand.strand, &resp->base );
179 Message_Release(&resp->base);
180 }
|
181 mike 1.1
|
182 krisbash 1.4 Strand_Close( &interaction->strand.strand );
183 }
|
184 mike 1.1
|
185 krisbash 1.4 static void _DispEnumParent_Transport_Post( _In_ Strand* self_, _In_ Message* msg)
186 {
187 DEBUG_ASSERT( MI_FALSE ); // we dont expect any additional messages at this point
|
188 mike 1.1 }
189
|
190 krisbash 1.4 static void _DispEnumParent_Transport_PostControl( _In_ Strand* self, _In_ Message* msg)
|
191 mike 1.1 {
|
192 krisbash 1.4 DEBUG_ASSERT( MI_FALSE ); // not used yet
|
193 mike 1.1 }
194
|
195 krisbash 1.4 static void _DispEnumParent_Transport_Cancel( _In_ Strand* self)
|
196 mike 1.1 {
|
197 krisbash 1.4 // not used yet
|
198 mike 1.1 }
199
|
200 krisbash 1.4 static void _DispEnumParent_Finished( _In_ Strand* self_)
|
201 mike 1.1 {
|
202 krisbash 1.4 DispEnumParent* self = (DispEnumParent*)StrandMany_FromStrand(self_);
203 _DispEnumParent_Delete( self );
|
204 mike 1.1 }
205
|
206 krisbash 1.4 //DISPENUMPARENT_STRANDAUX_ENUMDONE
207 static void _DispEnumParent_EnumDone( _In_ Strand* self_)
|
208 mike 1.1 {
|
209 krisbash 1.4 DispEnumParent* self = (DispEnumParent*)StrandMany_FromStrand(self_);
|
210 mike 1.1
|
211 krisbash 1.4 trace_DispEnumDone(self, self->strand.numEntries, self->result );
212
213 self->done = MI_TRUE;
214
215 if( 0 == self->strand.numEntries )
|
216 mike 1.1 {
|
217 krisbash 1.4 _DispEnumParent__SendLastResponse( self );
|
218 mike 1.1 }
219 }
220
|
221 krisbash 1.4 /*
222 This object manages a a "Parent" enumeration on the dispatcher level.
223 Enumerations in this context include also Associations and References.
224 The dispatcher converts that parent enumertion coming from the client
225 into several actual child enumerations that can go to the same or different providers
226 for each of those child enumerations a "EnumEntry" object (see more info below) will be
227 created and attached to this Parent enumeration using the one-to-many
228 strand interface (StrandMany).
229
230 Behavior:
231 - Post and PostControl are not used yet as no secondary messages after
232 initial request are issued currently
233 - Cancel is also not implememented as Cancelation e2e is not implemented
234 - Shutdown:
235 once all the child enumerations have been issued DISPENUMPARENT_STRANDAUX_ENUMDONE
236 is scheduled on the parent, what in turn set the done flag to true and sends the last response
237 (final result) to the transport. That would happen if all the enumerations ran in the same thread
238 as by that point all of them would have completed. However if one or more enumerations
239 are run in the own thread (by the provider or out-of-proc) then may not be completed
240 at that point and then the sending of last response and shutdown will occur once
241 the last enumeration is closed and deleted and the parent is notified on
242 krisbash 1.4 _DispEnumParent_Entry_Deleted (implemented below on the internal FT)
243
244 Internal interface and unique features:
245 - When a message is sent internally (from EnumEntry) it is just sent pass
246 thru to the transport EXCEPT if it is a PostResultMsg as in that case the result
247 is just stored internally (if it is not success) as we are only returning one single
248 result to the parent interaction (managed on _DispEnumParent_Entry_Post below)
249 */
250 static StrandFT _DispEnumParent_TransportFT = {
251 _DispEnumParent_Transport_Post,
252 _DispEnumParent_Transport_PostControl,
253 NULL,
254 _DispEnumParent_Transport_Cancel,
255 NULL,
256 _DispEnumParent_Finished,
257 NULL,
258 _DispEnumParent_EnumDone,
259 NULL,
260 NULL,
261 NULL,
262 NULL };
263 krisbash 1.4
264 static void _DispEnumEntry_Provider_PostControl( _In_ Strand* self, _In_ Message* msg)
265 {
266 DEBUG_ASSERT( MI_FALSE ); // not used yet
267 }
|
268 mike 1.1
|
269 krisbash 1.4 static void _DispEnumEntry_Provider_Close( _In_ Strand* self )
|
270 mike 1.1 {
|
271 krisbash 1.4 if(!self->info.thisClosedOther)
|
272 mike 1.1 {
|
273 krisbash 1.4 // Just close back
274 Strand_Close( self );
|
275 mike 1.1 }
276 }
277
|
278 krisbash 1.4 /*
279 This object manages the interaction wich each particular provider enumeration
280 that a parent provider is divided into (see more info above on _DispEnumParent_TransportFT)
|
281 mike 1.1
|
282 krisbash 1.4 Behavior:
283 - PostControl is not used yet
284 - Posts are just passed pass thru (and acks are managed by StrandMany)
285 - Shutdown: once the provider side closes the interaction this object closes the
286 interaction back what will trigger automatically deletion of the object
287 */
288 static StrandFT _DispEnumEntry_ProviderFT = {
289 NULL,
290 _DispEnumEntry_Provider_PostControl,
291 NULL,
292 NULL,
293 _DispEnumEntry_Provider_Close,
294 NULL,
295 NULL,
296 NULL,
297 NULL,
298 NULL,
299 NULL,
300 NULL };
301
302 static void _DispEnumParent_Entry_Deleted( _In_ StrandMany* self_ )
|
303 mike 1.1 {
|
304 krisbash 1.4 DispEnumParent* self = (DispEnumParent*)self_;
|
305 mike 1.1
|
306 krisbash 1.4 DEBUG_ASSERT( NULL != self );
|
307 mike 1.1
|
308 krisbash 1.4 trace_DispEntryDeleted(self, self->strand.numEntries, self->done );
|
309 mike 1.1
|
310 krisbash 1.4 if( self->done && 0 == self->strand.numEntries )
311 {
312 _DispEnumParent__SendLastResponse( self );
|
313 mike 1.1 }
314 }
315
|
316 krisbash 1.4 static void _DispEnumParent_Entry_Post( _In_ StrandMany* self_, _In_ Message* msg)
|
317 mike 1.1 {
|
318 krisbash 1.4 DispEnumParent* self = (DispEnumParent*)self_;
|
319 mike 1.1
|
320 krisbash 1.4 DEBUG_ASSERT( NULL != self );
321
322 trace_DispPostingMessage( self->strand.strand.info.interaction.other, self_);
|
323 mike 1.1
|
324 krisbash 1.4 if( PostResultMsgTag == msg->tag )
|
325 mike 1.1 {
|
326 krisbash 1.4 PostResultMsg* rsp = (PostResultMsg*)msg;
|
327 mike 1.1
|
328 krisbash 1.4 if( MI_RESULT_OK != rsp->result && MI_RESULT_OK == self->result )
|
329 mike 1.1 {
|
330 krisbash 1.4 self->result = rsp->result;
|
331 mike 1.1 }
332
|
333 krisbash 1.4 // This is not posted here
334 }
335 else
336 {
337 Strand_Post( &self->strand.strand, msg );
|
338 mike 1.1 }
339 }
340
|
341 krisbash 1.4 // used for enums, associators, references and subcriptions
342 static StrandManyInternalFT _DispEnumParent_InternalFT = {
343 NULL,
344 _DispEnumParent_Entry_Deleted,
345 _DispEnumParent_Entry_Post,
346 NULL,
347 NULL,
348 NULL,
349 NULL,
350 NULL,
351 NULL,
352 NULL };
353
354 static MI_Result _DispatchEnumerateInstancesReq(
355 _In_ Disp* disp,
356 _In_ EnumerateInstancesReq* request,
357 _In_ const ZChar* className,
358 _In_opt_ EnumEntry* enumEntry,
359 _In_opt_ InteractionOpenParams* interactionParams )
|
360 mike 1.1 {
|
361 krisbash 1.4 const ProvRegEntry* provEntry;
362 MI_Result result;
363 EnumerateInstancesReq* msg;
364 AgentMgr_OpenCallbackData openCallbackData;
|
365 mike 1.1
|
366 krisbash 1.4 DEBUG_ASSERT( NULL != className );
367
368 /* Attempt to find a provider for this class */
369 provEntry = ProvReg_FindProviderForClass(&disp->provreg,
370 request->nameSpace, className, &result );
|
371 mike 1.1
|
372 krisbash 1.4 if (!provEntry)
373 {
374 return MI_RESULT_NOT_SUPPORTED;
375 }
|
376 mike 1.1
|
377 krisbash 1.4 /* Create new request to send to provider */
378 msg = EnumerateInstancesReq_New(request->base.base.operationId, request->base.base.flags);
379 if( NULL == msg )
380 {
381 trace_DispatchEnumerateInstancesReq_OutOfMemory();
382 return MI_RESULT_SERVER_LIMITS_EXCEEDED;
383 }
384
385 msg->base.options = request->base.options;
386 AuthInfo_Copy( &msg->base.authInfo, &request->base.authInfo );
387 msg->nameSpace = Batch_Tcsdup(msg->base.base.batch, request->nameSpace);
388 msg->className = Batch_Tcsdup(msg->base.base.batch, className);
389 msg->base.userAgent = request->base.userAgent;
|
390 mike 1.1
|
391 krisbash 1.4 if (!msg->nameSpace || !msg->className)
|
392 mike 1.1 {
|
393 krisbash 1.4 goto OutOfMemory;
|
394 mike 1.1 }
395
|
396 krisbash 1.4 /* Clone the query fields (if any) */
397 if (request->queryLanguage)
|
398 mike 1.1 {
|
399 krisbash 1.4 msg->queryLanguage = Batch_Tcsdup(msg->base.base.batch, request->queryLanguage);
400 if (!msg->queryLanguage)
401 {
402 goto OutOfMemory;
403 }
|
404 mike 1.1 }
405
|
406 krisbash 1.4 if( request->queryExpression )
|
407 mike 1.1 {
|
408 krisbash 1.4 msg->queryExpression = Batch_Tcsdup(msg->base.base.batch,request->queryExpression);
409 if (!msg->queryExpression)
|
410 mike 1.1 {
|
411 krisbash 1.4 goto OutOfMemory;
|
412 mike 1.1 }
413 }
|
414 krisbash 1.4
415 /* Save request's class name to allow provmgr pack back only base properties */
416 if( request->basePropertiesOnly )
|
417 mike 1.1 {
|
418 krisbash 1.4 msg->requestClassName = Batch_Tcsdup(msg->base.base.batch, request->className);
419 if (!msg->requestClassName)
420 {
421 goto OutOfMemory;
422 }
|
423 mike 1.1 }
424
|
425 krisbash 1.4 openCallbackData.self = &disp->agentmgr;
426 openCallbackData.proventry = provEntry;
427
428 if( NULL != enumEntry )
429 {
430 trace_DispatchEnumDispInteraction(tcs(className));
|
431 mike 1.1
|
432 krisbash 1.4 /* Send the request to provider manager */
433 Strand_Open( &enumEntry->strand.strand, AgentMgr_OpenCallback, &openCallbackData, &msg->base.base, MI_TRUE );
434 }
435 else
|
436 mike 1.1 {
|
437 krisbash 1.4 DEBUG_ASSERT( NULL != interactionParams );
438
439 // send it directly to AgentMgr
440 interactionParams->callbackData = &openCallbackData;
441 interactionParams->msg = &request->base.base;
442
443 trace_DispatchEnumDirectly(tcs(className));
444
445 AgentMgr_OpenCallback( interactionParams );
|
446 mike 1.1 }
447
448 /* Release the original message */
449 EnumerateInstancesReq_Release(msg);
450
|
451 krisbash 1.4 return MI_RESULT_OK;
|
452 mike 1.1
|
453 krisbash 1.4 OutOfMemory:
454 trace_DispatchEnumerateInstancesReq_OutOfMemory();
455 EnumerateInstancesReq_Release(msg);
456
457 return MI_RESULT_SERVER_LIMITS_EXCEEDED;
|
458 mike 1.1 }
459
|
460 krisbash 1.4 // Also used for References
|
461 mike 1.1 static MI_Boolean _DispatchAssocReq(
|
462 krisbash 1.4 _In_ Disp* disp,
463 _In_ AssociationsOfReq* req,
464 _In_ EnumEntry* enumEntry,
465 MessageTag tag )
|
466 mike 1.1 {
467 const ProvRegEntry* entry;
|
468 krisbash 1.4 AssociationsOfReq* msg;
469 const ZChar* className = enumEntry->className;
470 MI_Result result;
471 AgentMgr_OpenCallbackData openCallbackData;
|
472 mike 1.2
|
473 mike 1.1 /* Attempt to find a provider for this class */
|
474 krisbash 1.4 entry = ProvReg_FindProviderForClass(&disp->provreg,
475 req->nameSpace, className, &result );
476
477 if (!entry)
|
478 mike 1.1 {
|
479 krisbash 1.4 trace__DispatchAssocReq_OutOfMemory();
480 return MI_FALSE;
|
481 mike 1.1 }
482
483 /* Create new request to send to provider */
|
484 krisbash 1.4 msg = AssociationsOfReq_New(req->base.base.operationId, req->base.base.flags, tag);
485 msg->base.options = req->base.options;
486 AuthInfo_Copy( &msg->base.authInfo, &req->base.authInfo );
|
487 mike 1.1 /* original request will be kept for the request duration, so perform shallow copy only */
488 msg->nameSpace = req->nameSpace;
489 msg->assocClass = req->assocClass;
490 msg->resultClass = req->resultClass;
491 msg->role = req->role;
492 msg->resultRole = req->resultRole;
493 msg->instance = req->instance;
494 msg->packedInstancePtr = req->packedInstancePtr;
495 msg->packedInstanceSize = req->packedInstanceSize;
|
496 krisbash 1.4 msg->base.userAgent = req->base.userAgent;
|
497 mike 1.1
|
498 krisbash 1.4 msg->className = Batch_Tcsdup(msg->base.base.batch, className);
|
499 mike 1.1
|
500 krisbash 1.4 trace_DispatchAssoc(tcs(className));
501
502 /* Send the request to provider manager */
503 openCallbackData.self = &disp->agentmgr;
504 openCallbackData.proventry = entry;
505 Strand_Open( &enumEntry->strand.strand, AgentMgr_OpenCallback, &openCallbackData, &msg->base.base, MI_TRUE );
|
506 mike 1.1
|
507 krisbash 1.4 /* Release the original message */
508 AssociationsOfReq_Release(msg);
|
509 mike 1.1
|
510 krisbash 1.4 return MI_TRUE;
511 }
|
512 mike 1.1
|
513 krisbash 1.4 DispEnumParent* _DispEnumParent_New(
514 _In_ Disp* disp,
515 _In_ InteractionOpenParams* interactionParams )
516 {
517 DispEnumParent* self;
518
519 self = (DispEnumParent*)StrandMany_New(
520 STRAND_DEBUG( DispEnumParent )
521 &_DispEnumParent_TransportFT,
522 &_DispEnumParent_InternalFT,
523 sizeof( DispEnumParent ),
524 STRAND_FLAG_ENTERSTRAND,
525 interactionParams,
526 1,
527 NULL,
528 NULL,
529 NULL);
|
530 mike 1.1
|
531 krisbash 1.4 if(self)
|
532 mike 1.1 {
|
533 krisbash 1.4 RequestMsg* req = (RequestMsg*)interactionParams->msg;
534 DEBUG_ASSERT( NULL != req );
|
535 mike 1.1
|
536 krisbash 1.4 Message_AddRef( &req->base );
537 self->baseRequest = req;
538
539 self->disp = disp;
540 self->result = MI_RESULT_OK;
541
542 // As soon as we accept the open we can send the open msg ack
543 Strand_Ack( &self->strand.strand );
|
544 mike 1.1 }
|
545 krisbash 1.4
546 return self;
|
547 mike 1.1 }
548
|
549 krisbash 1.4 static MI_Result _HandleGetInstanceReq(
550 _In_ Disp* self,
551 _Inout_ InteractionOpenParams* interactionParams,
552 _In_ GetInstanceReq* req)
|
553 mike 1.1 {
554 MI_Result r;
|
555 krisbash 1.4 const ProvRegEntry* reg;
|
556 mike 1.1
|
557 krisbash 1.4 /* Validate input parameters */
558 if (!req->instanceName || !req->nameSpace)
559 return MI_RESULT_INVALID_PARAMETER;
|
560 mike 1.1
|
561 krisbash 1.4 // Find a provider for this class.
562 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
563 req->instanceName->classDecl->name, &r );
|
564 mike 1.1
|
565 krisbash 1.4 if (!reg)
566 {
567 trace_NoProviderForClass(
568 req->nameSpace,
569 req->instanceName->classDecl->name);
570 goto sendErrorBack;
571 }
|
572 mike 1.1
|
573 krisbash 1.4 // Send the request to provider manager.
574 r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
|
575 mike 1.1
576 if (r != MI_RESULT_OK)
577 {
|
578 krisbash 1.4 trace_AgentMgrHandleRequestForNS(
579 req->nameSpace);
580 goto sendErrorBack;
|
581 mike 1.1 }
582
|
583 krisbash 1.4 return MI_RESULT_OK;
|
584 mike 1.1
|
585 krisbash 1.4 sendErrorBack:
586 // Just abort creating any interaction at all
587 return r;
|
588 mike 1.1 }
589
|
590 krisbash 1.4 static MI_Result _HandleGetClassReq(
591 _In_ Disp* self,
592 _Inout_ InteractionOpenParams* interactionParams,
593 _In_ GetClassReq* req)
|
594 mike 1.1 {
|
595 krisbash 1.4 MI_Result r;
596 const ProvRegEntry* reg;
597 ProvRegEntry freg;
|
598 mike 1.1 ProvRegPosition pos;
599
600 /* Validate input parameters */
601 if (!req->className || !req->nameSpace)
602 return MI_RESULT_INVALID_PARAMETER;
603
|
604 krisbash 1.4 // client must specify classname for GetClass request
605 if(Tcscmp(req->className, PAL_T("*")) == 0)
606 return MI_RESULT_INVALID_CLASS;
|
607 mike 1.1
|
608 krisbash 1.4 memset( &freg, 0, sizeof(freg) );
|
609 mike 1.1
|
610 krisbash 1.4 // Find a provider for this class.
611 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
612 req->className, &r );
|
613 mike 1.1
|
614 krisbash 1.4 if (!reg)
|
615 mike 1.1 {
|
616 krisbash 1.4 if(MI_RESULT_INVALID_CLASS == r)
|
617 mike 1.1 {
|
618 krisbash 1.4 /* Checking if the requested class is a base class of an implemented class */
|
619 mike 1.1 r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
|
620 krisbash 1.4 req->className, MI_TRUE, &pos, MI_FALSE);
|
621 mike 1.1
|
622 krisbash 1.4 if(MI_RESULT_INVALID_CLASS == r)
|
623 mike 1.1 {
|
624 krisbash 1.4 /* Checking if the requested class is an extraclass (Class without key property or Class with key property but not part of any
625 class heirarchy of an implemented class.)
626 Class with valid providerFT is called as an implemented class */
627
628 /* In extra classes inheritance tree a namespace node is created only if there is at least one extra class in the namespace.
629 So namespace node need not exist in extra classes inheritance tree even for valid namespace */
630 r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
631 req->className, MI_TRUE, &pos, MI_TRUE);
|
632 mike 1.1
|
633 krisbash 1.4 if(MI_RESULT_INVALID_NAMESPACE == r)
634 r = MI_RESULT_INVALID_CLASS;
|
635 mike 1.1 }
|
636 krisbash 1.4 if (MI_RESULT_OK == r)
|
637 mike 1.1 {
|
638 krisbash 1.4 DEBUG_ASSERT(pos.start != NULL);
639 MapRegPositionValuesToRegEntry(&freg, &pos);
640 freg.nameSpace = req->nameSpace;
641 freg.nameSpaceHash = Hash(req->nameSpace);
|
642 mike 1.1 }
643 }
|
644 krisbash 1.4
645 if (MI_RESULT_OK != r)
|
646 mike 1.1 {
|
647 krisbash 1.4 trace_NoProviderForClass(
648 req->nameSpace,
649 req->className);
650 goto sendErrorBack;
|
651 mike 1.1 }
652 }
|
653 krisbash 1.4 else
|
654 mike 1.1 {
|
655 krisbash 1.4 freg = *reg;
|
656 mike 1.1 }
657
658 // Send the request to provider manager.
|
659 krisbash 1.4 r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, &freg);
|
660 mike 1.1
661 if (r != MI_RESULT_OK)
662 {
|
663 krisbash 1.4 trace_AgentMgrHandleRequestForNS(
664 req->nameSpace);
|
665 mike 1.1 goto sendErrorBack;
666 }
667
668 return MI_RESULT_OK;
669
670 sendErrorBack:
|
671 krisbash 1.4 // Just abort creating any interaction at all
672 return r;
|
673 mike 1.1 }
674
675 static MI_Result _HandleCreateInstanceReq(
|
676 krisbash 1.4 _In_ Disp* self,
677 _Inout_ InteractionOpenParams* interactionParams,
678 _In_ CreateInstanceReq* req)
|
679 mike 1.1 {
680 MI_Result r;
681 const ProvRegEntry* reg;
682
683 /* Validate input parameters */
684 if (!req->instance || !req->nameSpace)
685 return MI_RESULT_INVALID_PARAMETER;
686
687 // Find a provider for this class.
688 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
|
689 krisbash 1.4 req->instance->classDecl->name, &r );
|
690 mike 1.1
691 if (!reg)
692 {
|
693 krisbash 1.4 trace_NoProviderForClass(
694 req->nameSpace,
695 req->instance->classDecl->name);
|
696 mike 1.1 goto sendErrorBack;
697 }
698
699 // Send the request to provider manager.
|
700 krisbash 1.4 r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
|
701 mike 1.1
702 if (r != MI_RESULT_OK)
703 {
|
704 krisbash 1.4 trace_AgentMgrHandleRequestForNS(
705 req->nameSpace);
|
706 mike 1.1 goto sendErrorBack;
707 }
708
709 return MI_RESULT_OK;
710
711 sendErrorBack:
|
712 krisbash 1.4 // Just abort creating any interaction at all
713 return r;
|
714 mike 1.1 }
715
716 static MI_Result _HandleModifyInstanceReq(
|
717 krisbash 1.4 _In_ Disp* self,
718 _Inout_ InteractionOpenParams* interactionParams,
719 _In_ ModifyInstanceReq* req)
|
720 mike 1.1 {
721 MI_Result r;
722 const ProvRegEntry* reg;
723
724 /* Validate input parameters */
725 if (!req->instance || !req->nameSpace)
726 return MI_RESULT_INVALID_PARAMETER;
727
728 // Find a provider for this class.
729 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
|
730 krisbash 1.4 req->instance->classDecl->name, &r );
|
731 mike 1.1
732 if (!reg)
733 {
|
734 krisbash 1.4 trace_NoProviderForClass(
735 req->nameSpace,
736 req->instance->classDecl->name);
|
737 mike 1.1 goto sendErrorBack;
738 }
739
740 // Send the request to provider manager.
|
741 krisbash 1.4 r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
|
742 mike 1.1
743 if (r != MI_RESULT_OK)
744 {
|
745 krisbash 1.4 trace_AgentMgrHandleRequestForNS(
746 req->nameSpace);
|
747 mike 1.1 goto sendErrorBack;
748 }
749
750 return MI_RESULT_OK;
751
752 sendErrorBack:
|
753 krisbash 1.4 // Just abort creating any interaction at all
754 return r;
|
755 mike 1.1 }
756
757 static MI_Result _HandleDeleteInstanceReq(
|
758 krisbash 1.4 _In_ Disp* self,
759 _Inout_ InteractionOpenParams* interactionParams,
760 _In_ DeleteInstanceReq* req)
|
761 mike 1.1 {
762 MI_Result r;
763 const ProvRegEntry* reg;
764
765 /* Validate input parameters */
766 if (!req->instanceName || !req->nameSpace)
767 return MI_RESULT_INVALID_PARAMETER;
768
769 // Find a provider for this class.
770 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
|
771 krisbash 1.4 req->instanceName->classDecl->name, &r);
|
772 mike 1.1
773 if (!reg)
774 {
|
775 krisbash 1.4 trace_NoProviderForClass(
776 req->nameSpace,
777 req->instanceName->classDecl->name);
|
778 mike 1.1 goto sendErrorBack;
779 }
780
781 // Send the request to provider manager.
|
782 krisbash 1.4 r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
|
783 mike 1.1
784 if (r != MI_RESULT_OK)
785 {
|
786 krisbash 1.4 trace_AgentMgrHandleRequestForNS(
787 req->nameSpace);
|
788 mike 1.1 goto sendErrorBack;
789 }
790
791 return MI_RESULT_OK;
792
793 sendErrorBack:
|
794 krisbash 1.4 // Just abort creating any interaction at all
795 return r;
|
796 mike 1.1 }
797
|
798 krisbash 1.4 static MI_Result _HandleInvokeReq(
799 _In_ Disp* self,
800 _Inout_ InteractionOpenParams* interactionParams,
801 _In_ InvokeReq* req)
|
802 mike 1.1 {
803 MI_Result r;
|
804 krisbash 1.4 const ProvRegEntry* reg;
805 MI_ConstString cn = 0;
|
806 mike 1.1
807 /* Validate input parameters */
|
808 krisbash 1.4 if (!req->nameSpace)
|
809 mike 1.1 return MI_RESULT_INVALID_PARAMETER;
810
|
811 krisbash 1.4 if (req->className)
812 cn = req->className;
813 else if (req->instance)
814 cn = req->instance->classDecl->name;
|
815 mike 1.1
|
816 krisbash 1.4 if (!cn)
817 {
818 r = MI_RESULT_INVALID_CLASS;
819 trace_ClassNameIsExpectedForInvoke();
820 goto sendErrorBack;
821 }
|
822 mike 1.1
823
|
824 krisbash 1.4 // Find a provider for this class.
825 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, cn, &r);
|
826 mike 1.1
|
827 krisbash 1.4 if (!reg)
828 {
829 trace_FoundNoProvider(
830 cn);
|
831 mike 1.1 goto sendErrorBack;
|
832 krisbash 1.4 }
|
833 mike 1.1
834 // Send the request to provider manager.
|
835 krisbash 1.4 r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
|
836 mike 1.1
837 if (r != MI_RESULT_OK)
838 {
|
839 krisbash 1.4 trace_AgentMgrHandleRequestForNS(
840 req->nameSpace);
|
841 mike 1.1 goto sendErrorBack;
842 }
843
844 return MI_RESULT_OK;
845
846 sendErrorBack:
|
847 krisbash 1.4 // Just abort creating any interaction at all
848 return r;
|
849 mike 1.1 }
850
|
851 krisbash 1.4 static MI_Result _HandleEnumerateInstancesReq(
852 _In_ Disp* self,
853 _Inout_ InteractionOpenParams* interactionParams,
854 _In_ EnumerateInstancesReq* req)
|
855 mike 1.1 {
|
856 krisbash 1.4 MI_Result r = MI_RESULT_FAILED;
857 MI_Boolean sentOk = MI_FALSE;
858 WQL_Dialect dialect;
859 DispEnumParent* enumInteraction;
860 EnumEntry* enumEntry;
861 EnumEntry* enumEntryHead = NULL;
|
862 mike 1.1
863 /* Validate input parameters */
864 if (!req->nameSpace)
865 return MI_RESULT_INVALID_PARAMETER;
866
|
867 krisbash 1.4 /* Precompile the query */
868 if (req->queryLanguage || req->queryExpression)
869 {
870 /* Fail if either query language or expression is missing */
871 if (!req->queryLanguage || !req->queryExpression)
872 {
873 trace_QueryLanguageOrExpressionMissing();
874 return MI_RESULT_INVALID_QUERY;
875 }
876
877 /* Reject non-WQL queries */
878 if (Tcscasecmp(req->queryLanguage, MI_QUERY_DIALECT_WQL) == 0)
879 {
880 dialect = WQL_DIALECT_WQL;
881 }
882 else if (Tcscasecmp(req->queryLanguage, MI_QUERY_DIALECT_CQL) == 0)
883 {
884 dialect = WQL_DIALECT_CQL;
885 }
886 else
887 {
888 krisbash 1.4 trace_UnsupportedQueryLanguage(tcs(req->queryLanguage));
889 return MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED;
890 }
891
892 /* Compile the query */
893 {
894 req->wql = WQL_Parse(req->queryExpression, req->base.base.batch,
895 dialect);
896
897 if (!req->wql)
898 {
899 trace_InvalidQueryExpression(tcs(req->queryExpression));
900 return MI_RESULT_INVALID_QUERY;
901 }
902 }
903
904 /* WQL queries from WinRM pass '*' as the class name */
905
906 if (!req->className || (Tcscmp(req->className, PAL_T("*")) == 0))
907 {
908 req->className = req->wql->className;
909 krisbash 1.4 }
|
910 mike 1.1
|
911 krisbash 1.4 /* Verify that the query classname matches the enumeration classname */
912 if (Tcscmp(req->wql->className, req->className) != 0)
913 {
914 trace_QueryEnumClassnameMismatch(
915 tcs(req->wql->className), tcs(req->className));
916 return MI_RESULT_INVALID_QUERY;
917 }
918 }
919 else if (!req->className)
|
920 mike 1.1 {
|
921 krisbash 1.4 trace_EnumHasNoClassname();
922 return MI_RESULT_INVALID_PARAMETER;
|
923 mike 1.1 }
924
|
925 krisbash 1.4 if (req->deepInheritance)
926 {
927 ProvRegPosition pos;
928 EnumEntry* enumEntryPrev;
929
930 /* create the interaction that will keep track of results from providers */
931 enumInteraction = _DispEnumParent_New(
932 self,
933 interactionParams);
934 if (!enumInteraction)
935 {
936 trace_Disp_ErrorInteractionAlloc();
937 return MI_RESULT_FAILED;
938 }
939
940 /* Send to direct name */
941 /* Start by sending to direct name */
942 enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
943 &enumInteraction->strand,
944 &_DispEnumEntry_ProviderFT,
945 sizeof(EnumEntry),
946 krisbash 1.4 STRAND_FLAG_ENTERSTRAND,
947 NULL);
948 if( NULL == enumEntry )
949 {
950 trace_Disp_ErrorEnumEntryAlloc();
951 goto sendErrorBack_Opened;
952 }
953 r = StrandMany_AddEntry( &enumEntry->strand );
954 if( MI_RESULT_OK != r )
955 {
956 StrandEntry_DeleteNoAdded( &enumEntry->strand );
957 goto sendErrorBack_Opened;
958 }
959 enumEntry->className = req->className;
960 enumEntryHead = enumEntry;
961 enumEntryPrev = enumEntry;
962
963 /* Begin enumeration of classes for this request */
964 {
965 r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
966 req->className, MI_TRUE, &pos, MI_FALSE);
967 krisbash 1.4
968 if (MI_RESULT_OK != r)
969 {
970 {
971 /* Checking if the class is in extra classes to return appropriate error */
972 MI_Result result;
973 result = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
974 req->className, MI_TRUE, &pos, MI_TRUE);
975 if(MI_RESULT_OK == result)
976 {
977 ProvReg_EndClasses(&pos);
978 r = MI_RESULT_NOT_SUPPORTED;
979 goto sendErrorBack_Opened;
980 }
981 }
982 trace_ProvReg_BeginClasses_Failed(
983 r, tcs(Result_ToString(r)));
984
985 trace_DispEnum_UnknownClass(
986 tcs(req->nameSpace), tcs(req->className));
987
988 krisbash 1.4 /* send error back to caller */
989 goto sendErrorBack_Opened;
990 }
991 }
992
993 /* While more classes */
994 for (;;)
995 {
996 const ZChar* derived = NULL;
997 MI_Boolean done;
998
999 r = ProvReg_NextClass(&pos, &derived, &done);
1000
1001 if (done)
1002 break;
1003
1004 if (MI_RESULT_OK != r)
1005 {
1006 trace_ProvReg_NextClass_Failed(
1007 r, tcs(Result_ToString(r)));
1008
1009 krisbash 1.4 trace_DispEnum_UnknownClass(
1010 tcs(req->nameSpace), tcs(req->className));
1011
1012 /* send error back to caller */
1013 goto sendErrorBack_Opened;
1014 }
1015
1016 enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
1017 &enumInteraction->strand,
1018 &_DispEnumEntry_ProviderFT,
1019 sizeof(EnumEntry),
1020 STRAND_FLAG_ENTERSTRAND,
1021 NULL);
1022 if( NULL == enumEntry )
1023 {
1024 trace_Disp_ErrorEnumEntryAlloc();
1025 goto sendErrorBack_Opened;
1026 }
1027
1028 r = StrandMany_AddEntry( &enumEntry->strand );
1029 if( MI_RESULT_OK != r )
1030 krisbash 1.4 {
1031 trace_Disp_ErrorAddEntry();
1032 StrandEntry_DeleteNoAdded( &enumEntry->strand );
1033 goto sendErrorBack_Opened;
1034 }
1035
1036 // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
1037 enumEntry->className = Batch_Tcsdup(req->base.base.batch, derived);
1038 enumEntry->next = NULL;
1039 enumEntryPrev->next = enumEntry;
1040 enumEntryPrev = enumEntry;
1041 }
1042
1043 /* Finalize enumeration */
1044 {
1045 r = ProvReg_EndClasses(&pos);
1046
1047 if (MI_RESULT_OK != r)
1048 {
1049 trace_ProvReg_EndClasses_Failed(
1050 r, tcs(Result_ToString(r)));
1051 krisbash 1.4 /* send error back to caller */
1052 goto sendErrorBack_Opened;
1053 }
1054 }
1055
1056 Strand_Leave( &enumInteraction->strand.strand );
|
1057 mike 1.1
|
1058 krisbash 1.4 // Now go thru the added entries and dispatch the interactions
1059 enumEntry = enumEntryHead;
1060 while( NULL != enumEntry )
1061 {
1062 // Move to the next one before the object can be deleted by itself or by delete below
1063 enumEntryPrev = enumEntry;
1064 enumEntry = enumEntry->next;
1065 if( _DispatchEnumerateInstancesReq(self, req, enumEntryPrev->className, enumEntryPrev, NULL) == MI_RESULT_OK)
1066 {
1067 sentOk = MI_TRUE;
1068 }
1069 else
1070 {
1071 StrandEntry_Delete( &enumEntryPrev->strand );
1072 }
1073 }
1074 enumEntryHead = NULL;
1075
1076 /* Fail if no provider was found for request */
1077 if (!sentOk)
1078 {
1079 krisbash 1.4 trace_FoundNoProvider(
1080 req->className);
1081 r = MI_RESULT_NOT_SUPPORTED;
1082 goto sendErrorBack_Opened;
1083 }
|
1084 mike 1.1
|
1085 krisbash 1.4 StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
1086 } /* if deep*/
1087 else
|
1088 mike 1.1 {
|
1089 krisbash 1.4 /* Checking to see if the requested className is valid */
1090 ProvRegPosition pos;
1091 r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
1092 req->className, MI_TRUE, &pos, MI_FALSE);
1093
1094 if (MI_RESULT_OK != r)
1095 {
1096 /* Checking if the class is in extra classes to return appropriate error */
1097 MI_Result result;
1098 result = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
1099 req->className, MI_TRUE, &pos, MI_TRUE);
1100 if(MI_RESULT_OK == result)
1101 {
1102 r = MI_RESULT_NOT_SUPPORTED;
1103 ProvReg_EndClasses(&pos);
1104 }
1105 return r;
1106 }
1107 else
1108 {
1109 ProvReg_EndClasses(&pos);
1110 krisbash 1.4 }
1111
1112 // no need to create new interaction
1113 return _DispatchEnumerateInstancesReq(self, req, req->className, NULL, interactionParams);
|
1114 mike 1.1 }
1115
|
1116 krisbash 1.4 return MI_RESULT_OK;
|
1117 mike 1.1
|
1118 krisbash 1.4 sendErrorBack_Opened:
1119 // Delete not dispatched entries
1120 enumEntry = enumEntryHead;
1121 while( NULL != enumEntry )
|
1122 mike 1.1 {
|
1123 krisbash 1.4 StrandEntry_Delete( &enumEntry->strand );
1124 enumEntry = enumEntry->next;
|
1125 mike 1.1 }
|
1126 krisbash 1.4
1127 // send error back to caller
1128 _SendErrorResponse_Opened(interactionParams, enumInteraction, r, MI_FALSE );
|
1129 mike 1.1 return MI_RESULT_OK;
1130 }
1131
1132 static MI_Result _HandleAssociatorsOfReq(
|
1133 krisbash 1.4 _In_ Disp* self,
1134 _Inout_ InteractionOpenParams* interactionParams,
1135 _In_ AssociationsOfReq* req)
|
1136 mike 1.1 {
|
1137 krisbash 1.4 int res;
1138 MI_Result r = MI_RESULT_FAILED;
|
1139 mike 1.1 MI_ConstString cn = 0;
1140 ProvRegAssocPosition pos;
1141 MI_Boolean sentOk = MI_FALSE;
|
1142 krisbash 1.4 HashMap classNames;
1143 DispEnumParent* enumInteraction;
1144 EnumEntry* enumEntry;
1145 EnumEntry* enumEntryHead = NULL;
1146 EnumEntry* enumEntryPrev = NULL;
|
1147 mike 1.2
1148 /* Create a hash table of class names */
1149
|
1150 krisbash 1.4 res = HashMap_Init(
|
1151 mike 1.2 &classNames,
1152 64,
1153 ClassNameHash,
1154 ClassNameEqual,
1155 ClassNameRelease);
1156
|
1157 krisbash 1.4 if (res != 0)
|
1158 mike 1.2 return MI_RESULT_FAILED;
|
1159 mike 1.1
1160 /* Validate input parameters */
1161 if (!req->instance || !req->nameSpace)
1162 return MI_RESULT_INVALID_PARAMETER;
1163
|
1164 krisbash 1.4 /* create the interaction that will keep track of results from providers */
1165 enumInteraction = _DispEnumParent_New(
1166 self,
1167 interactionParams);
1168 if (!enumInteraction)
1169 {
1170 trace_Disp_ErrorInteractionAlloc();
1171 HashMap_Destroy(&classNames);
|
1172 mike 1.1 return MI_RESULT_FAILED;
|
1173 krisbash 1.4 }
|
1174 mike 1.1
1175 r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,
1176 req->instance->classDecl->name,
1177 req->assocClass, req->resultClass, &pos);
1178
1179 if (MI_RESULT_OK != r)
1180 {
|
1181 krisbash 1.4 trace_ProvReg_BeginAssocClasses_Failed(r, tcs(Result_ToString(r)));
|
1182 mike 1.1
1183 /* send error back to caller */
|
1184 krisbash 1.4 goto sendErrorBack_Opened;
|
1185 mike 1.1 }
1186
|
1187 mike 1.2 /* ATTN: there is a bug in the provider registration tree causing
1188 * the association provider to be called twice. To avoid this for now,
1189 * we maintain a hash table of already dispatched classes.
1190 */
1191
|
1192 mike 1.1 /* While more classes */
1193 for (;;)
1194 {
1195 MI_Boolean done;
1196 r = ProvReg_NextAssocClass(&pos, &cn, &done);
1197
1198 if (done)
1199 break;
1200
1201 if (MI_RESULT_OK != r)
1202 {
|
1203 krisbash 1.4 trace_ProvReg_NextAssocClass_Failed(r, tcs(Result_ToString(r)));
1204
|
1205 mike 1.1 /* send error back to caller */
|
1206 krisbash 1.4 goto sendErrorBack_Opened;
|
1207 mike 1.1 }
1208
|
1209 mike 1.2 /* Check whether this class has been dispatched */
1210 {
1211 ClassNameBucket bucket;
|
1212 krisbash 1.4 bucket.key = (ZChar*)cn;
|
1213 mike 1.2
|
1214 krisbash 1.4 if (!HashMap_Find(&classNames, (const HashBucket*)&bucket))
|
1215 mike 1.2 {
|
1216 krisbash 1.4 enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
1217 &enumInteraction->strand,
1218 &_DispEnumEntry_ProviderFT,
1219 sizeof(EnumEntry),
1220 STRAND_FLAG_ENTERSTRAND,
1221 NULL);
1222 if( NULL == enumEntry )
1223 {
1224 trace_Disp_ErrorEnumEntryAlloc();
1225 goto sendErrorBack_Opened;
1226 }
1227
1228 r = StrandMany_AddEntry( &enumEntry->strand );
1229 if( MI_RESULT_OK != r )
1230 {
1231 trace_Disp_ErrorAddEntry();
1232 StrandEntry_DeleteNoAdded( &enumEntry->strand );
1233 goto sendErrorBack_Opened;
1234 }
1235
1236 // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
1237 krisbash 1.4 enumEntry->className = Batch_Tcsdup(req->base.base.batch, cn);
1238 enumEntry->next = NULL;
1239 if( NULL == enumEntryHead )
1240 {
1241 enumEntryHead = enumEntry;
1242 }
1243 else
1244 {
1245 enumEntryPrev->next = enumEntry;
1246 }
1247 enumEntryPrev = enumEntry;
|
1248 mike 1.2
1249 {
|
1250 krisbash 1.4 ClassNameBucket* bucket = (ClassNameBucket*)PAL_Calloc(
|
1251 mike 1.2 1, sizeof(ClassNameBucket));
1252
1253 if (!bucket)
1254 {
1255 r = MI_RESULT_FAILED;
|
1256 krisbash 1.4 goto sendErrorBack_Opened;
|
1257 mike 1.2 }
1258
|
1259 krisbash 1.4 bucket->key = PAL_Tcsdup(cn);
|
1260 mike 1.2
|
1261 krisbash 1.4 if (HashMap_Insert(&classNames, (HashBucket*)bucket) != 0)
|
1262 mike 1.2 {
1263 r = MI_RESULT_FAILED;
|
1264 krisbash 1.4 goto sendErrorBack_Opened;
|
1265 mike 1.2 }
1266 }
1267 }
1268 }
|
1269 mike 1.1 }
1270
1271 /* Finalize enumeration */
1272 {
1273 r = ProvReg_EndAssocClasses(&pos);
1274
1275 if (MI_RESULT_OK != r)
1276 {
|
1277 krisbash 1.4 trace_ProvReg_EndAssocClasses_Failed(r, tcs(Result_ToString(r)));
1278
|
1279 mike 1.1 /* send error back to caller */
|
1280 krisbash 1.4 goto sendErrorBack_Opened;
|
1281 mike 1.1 }
1282 }
1283
|
1284 krisbash 1.4 Strand_Leave( &enumInteraction->strand.strand );
1285
1286 // Now go thru the added entries and dispatch the interactions
1287 enumEntry = enumEntryHead;
1288 while( NULL != enumEntry )
1289 {
1290 // Move to the next one before the object can be deleted by itself or by delete below
1291 enumEntryPrev = enumEntry;
1292 enumEntry = enumEntry->next;
1293 if (_DispatchAssocReq(self, req, enumEntryPrev, AssociatorsOfReqTag))
1294 {
1295 sentOk = MI_TRUE;
1296 }
1297 else
1298 {
1299 StrandEntry_Delete( &enumEntryPrev->strand );
1300 }
1301 }
1302 enumEntryHead = NULL;
1303
1304 HashMap_Destroy(&classNames);
1305 krisbash 1.4
|
1306 mike 1.1 /* Fail if no provider was found for request */
1307 if (!sentOk)
1308 {
|
1309 krisbash 1.4 trace_FoundNoProvider(
1310 tcs(req->instance->classDecl->name));
1311 _SendErrorResponse_Opened(interactionParams, enumInteraction, MI_RESULT_NOT_SUPPORTED, MI_TRUE );
1312 return MI_RESULT_OK;
|
1313 mike 1.1 }
1314
|
1315 krisbash 1.4 StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
1316 return MI_RESULT_OK;
1317
1318 sendErrorBack_Opened:
1319 HashMap_Destroy(&classNames);
1320 // Delete not dispatched entries
1321 enumEntry = enumEntryHead;
1322 while( NULL != enumEntry )
1323 {
1324 StrandEntry_Delete( &enumEntry->strand );
1325 enumEntry = enumEntry->next;
|
1326 mike 1.1 }
|
1327 krisbash 1.4
1328 // send error back to caller
1329 _SendErrorResponse_Opened(interactionParams, enumInteraction, r, MI_FALSE );
|
1330 mike 1.1 return MI_RESULT_OK;
1331 }
1332
1333 static MI_Result _HandleReferencesOfReq(
|
1334 krisbash 1.4 _In_ Disp* self,
1335 _Inout_ InteractionOpenParams* interactionParams,
1336 _In_ AssociationsOfReq* req)
|
1337 mike 1.1 {
|
1338 krisbash 1.4 MI_Result r = MI_RESULT_FAILED;
|
1339 mike 1.1 MI_ConstString cn = 0;
1340 ProvRegAssocPosition pos;
1341 MI_Boolean sentOk = MI_FALSE;
|
1342 krisbash 1.4 DispEnumParent* enumInteraction;
1343 EnumEntry* enumEntry;
1344 EnumEntry* enumEntryHead = NULL;
1345 EnumEntry* enumEntryPrev = NULL;
|
1346 mike 1.1
1347 /* Validate input parameters */
1348 if (!req->instance || !req->nameSpace)
1349 return MI_RESULT_INVALID_PARAMETER;
1350
|
1351 krisbash 1.4 /* create the interaction that will keep track of results from providers */
1352 enumInteraction = _DispEnumParent_New(
1353 self,
1354 interactionParams);
1355 if (!enumInteraction)
1356 {
1357 trace_Disp_ErrorInteractionAlloc();
|
1358 mike 1.1 return MI_RESULT_FAILED;
|
1359 krisbash 1.4 }
|
1360 mike 1.1
|
1361 krisbash 1.4 /* resultClass parameter of ReferencesOf operation contains association class name.
1362 Here using req->resultClass for passing assocClassName to ProvReg_BeginAssocClasses function */
|
1363 mike 1.1 r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,
1364 req->instance->classDecl->name,
|
1365 krisbash 1.4 req->resultClass, 0, &pos);
|
1366 mike 1.1
1367 if (MI_RESULT_OK != r)
1368 {
|
1369 krisbash 1.4 trace_ProvReg_BeginAssocClasses_Failed(r, tcs(Result_ToString(r)));
|
1370 mike 1.1
1371 /* send error back to caller */
|
1372 krisbash 1.4 goto sendErrorBack_Opened;
|
1373 mike 1.1 }
1374
1375 /* While more classes */
1376 for (;;)
1377 {
1378 MI_Boolean done;
1379 r = ProvReg_NextAssocClass(&pos, &cn, &done);
1380
1381 if (done)
1382 break;
1383
1384 if (MI_RESULT_OK != r)
1385 {
|
1386 krisbash 1.4 trace_ProvReg_NextAssocClass_Failed(r, tcs(Result_ToString(r)));
1387
|
1388 mike 1.1 /* send error back to caller */
|
1389 krisbash 1.4 goto sendErrorBack_Opened;
|
1390 mike 1.1 }
1391
|
1392 krisbash 1.4 enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
1393 &enumInteraction->strand,
1394 &_DispEnumEntry_ProviderFT,
1395 sizeof(EnumEntry),
1396 STRAND_FLAG_ENTERSTRAND,
1397 NULL);
1398 if( NULL == enumEntry )
1399 {
1400 trace_Disp_ErrorEnumEntryAlloc();
1401 goto sendErrorBack_Opened;
1402 }
1403
1404 r = StrandMany_AddEntry( &enumEntry->strand );
1405 if( MI_RESULT_OK != r )
1406 {
1407 trace_Disp_ErrorAddEntry();
1408 StrandEntry_DeleteNoAdded( &enumEntry->strand );
1409 goto sendErrorBack_Opened;
1410 }
1411
1412 // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
1413 krisbash 1.4 enumEntry->className = Batch_Tcsdup(req->base.base.batch, cn);
1414 enumEntry->next = NULL;
1415 if( NULL == enumEntryHead )
1416 {
1417 enumEntryHead = enumEntry;
1418 }
1419 else
1420 {
1421 enumEntryPrev->next = enumEntry;
1422 }
1423 enumEntryPrev = enumEntry;
|
1424 mike 1.1 }
1425
1426 /* Finalize enumeration */
1427 {
1428 r = ProvReg_EndAssocClasses(&pos);
1429
1430 if (MI_RESULT_OK != r)
1431 {
|
1432 krisbash 1.4 trace_ProvReg_EndAssocClasses_Failed(r, tcs(Result_ToString(r)));
1433
|
1434 mike 1.1 /* send error back to caller */
|
1435 krisbash 1.4 goto sendErrorBack_Opened;
|
1436 mike 1.1 }
1437 }
1438
|
1439 krisbash 1.4 Strand_Leave( &enumInteraction->strand.strand );
1440
1441 // Now go thru the added entries and dispatch the interactions
1442 enumEntry = enumEntryHead;
1443 while( NULL != enumEntry )
1444 {
1445 // Move to the next one before the object can be deleted by itself or by delete below
1446 enumEntryPrev = enumEntry;
1447 enumEntry = enumEntry->next;
1448 if (_DispatchAssocReq(self, req, enumEntryPrev, ReferencesOfReqTag))
1449 {
1450 sentOk = MI_TRUE;
1451 }
1452 else
1453 {
1454 StrandEntry_Delete( &enumEntryPrev->strand );
1455 }
1456 }
1457 enumEntryHead = NULL;
1458
|
1459 mike 1.1 /* Fail if no provider was found for request */
1460 if (!sentOk)
1461 {
|
1462 krisbash 1.4 trace_FoundNoProvider(
1463 tcs(req->instance->classDecl->name));
1464 _SendErrorResponse_Opened(interactionParams, enumInteraction, MI_RESULT_NOT_SUPPORTED, MI_TRUE );
1465 return MI_RESULT_OK;
|
1466 mike 1.1 }
1467
|
1468 krisbash 1.4 StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
1469 return MI_RESULT_OK;
1470
1471 sendErrorBack_Opened:
1472 // Delete not dispatched entries
1473 enumEntry = enumEntryHead;
1474 while( NULL != enumEntry )
1475 {
1476 StrandEntry_Delete( &enumEntry->strand );
1477 enumEntry = enumEntry->next;
|
1478 mike 1.1 }
|
1479 krisbash 1.4
1480 // send error back to caller
1481 _SendErrorResponse_Opened(interactionParams, enumInteraction, r, FALSE );
1482 return MI_RESULT_OK;
1483 }
|
1484 mike 1.1
|
1485 krisbash 1.4 #ifndef DISABLE_INDICATION
1486 static MI_Result _HandleSubscribeReq(
1487 _In_ Disp* self,
1488 _Inout_ InteractionOpenParams* params )
1489 {
1490 params->callbackData = self->indmgr;
1491 IndiMgr_HandleSubscribeReq(params);
|
1492 mike 1.1 return MI_RESULT_OK;
1493 }
|
1494 krisbash 1.4 #endif /* ifndef DISABLE_INDICATION */
|
1495 mike 1.1
1496 /*
1497 **==============================================================================
1498 **
1499 ** Public definitions
1500 **
1501 **==============================================================================
1502 */
1503
1504 MI_Result Disp_Init(Disp* self, Selector* selector)
1505 {
1506 /* Check parameters */
1507 if (!self)
1508 return MI_RESULT_INVALID_PARAMETER;
1509
1510 memset(self, 0, sizeof(Disp));
1511
1512 #if 0
1513 /* Initialize the provider registry */
|
1514 krisbash 1.4 MI_RETURN_ERR(ProvReg_Init(&self->provreg, OMI_GetPath(ID_REGISTERFILE)));
|
1515 mike 1.1 #else
1516 MI_RETURN_ERR(ProvReg_Init2(&self->provreg));
1517 #endif
1518
1519 /* Initialize the provider manager */
1520 MI_RETURN_ERR(AgentMgr_Init(&self->agentmgr, selector));
1521
|
1522 krisbash 1.4 #ifndef DISABLE_INDICATION
1523 /* Initialize indication manager */
1524 self->indmgr = IndiMgr_NewFromDisp(self);
1525 if (NULL == self->indmgr)
1526 MI_RETURN_ERR(MI_RESULT_FAILED);
1527 #endif /* ifndef DISABLE_INDICATION */
|
1528 mike 1.1
1529 return MI_RESULT_OK;
1530 }
1531
|
1532 krisbash 1.5 MI_Result Disp_Reload(Disp* self)
1533 {
1534 if (!self)
1535 return MI_RESULT_INVALID_PARAMETER;
1536
1537 ProvReg_Destroy(&self->provreg);
1538 ProvReg_Init2(&self->provreg);
1539 return MI_RESULT_OK;
1540 }
1541
|
1542 mike 1.1 MI_Result Disp_Destroy(Disp* self)
1543 {
1544 MI_RETURN_ERR(AgentMgr_Destroy(&self->agentmgr));
1545 ProvReg_Destroy(&self->provreg);
1546
|
1547 krisbash 1.4 #ifndef DISABLE_INDICATION
1548 /* Shutdown indication manager */
1549 IndiMgr_Shutdown(self->indmgr);
1550 #endif /* ifndef DISABLE_INDICATION */
1551
|
1552 mike 1.1 /*ATTN! remove indication contexts! */
1553 return MI_RESULT_OK;
1554 }
1555
|
1556 krisbash 1.4 MI_Result Disp_HandleInteractionRequest(
1557 _In_ Disp* self,
1558 _Inout_ InteractionOpenParams* params )
|
1559 mike 1.1 {
|
1560 krisbash 1.4 Message* msg = params->msg;
1561
1562 trace_DispHandleInteractionRequest(self,
1563 params->interaction,
1564 msg,
1565 msg->tag,
1566 MessageName(msg->tag),
1567 msg->operationId);
1568
1569 DEBUG_ASSERT( NULL != self );
1570 DEBUG_ASSERT( NULL != params );
1571 DEBUG_ASSERT( NULL != params->interaction );
1572 DEBUG_ASSERT( NULL != params->msg );
1573
|
1574 mike 1.1 switch (msg->tag)
1575 {
|
1576 krisbash 1.4 case GetInstanceReqTag:
|
1577 mike 1.1 {
|
1578 krisbash 1.4 GetInstanceReq* req = (GetInstanceReq*)msg;
1579 return _HandleGetInstanceReq(self, params, req);
|
1580 mike 1.1 }
1581
|
1582 krisbash 1.4 case GetClassReqTag:
|
1583 mike 1.1 {
|
1584 krisbash 1.4 GetClassReq* req = (GetClassReq*)msg;
1585 return _HandleGetClassReq(self, params, req);
|
1586 mike 1.1 }
1587
|
1588 krisbash 1.4
|
1589 mike 1.1 case CreateInstanceReqTag:
1590 {
1591 CreateInstanceReq* req = (CreateInstanceReq*)msg;
|
1592 krisbash 1.4 return _HandleCreateInstanceReq(self, params, req);
|
1593 mike 1.1 }
1594
1595 case ModifyInstanceReqTag:
1596 {
1597 ModifyInstanceReq* req = (ModifyInstanceReq*)msg;
|
1598 krisbash 1.4 return _HandleModifyInstanceReq(self, params, req);
|
1599 mike 1.1 }
1600
1601 case DeleteInstanceReqTag:
1602 {
1603 DeleteInstanceReq* req = (DeleteInstanceReq*)msg;
|
1604 krisbash 1.4 return _HandleDeleteInstanceReq(self, params, req);
|
1605 mike 1.1 }
1606
1607 case InvokeReqTag:
1608 {
1609 InvokeReq* req = (InvokeReq*)msg;
|
1610 krisbash 1.4 return _HandleInvokeReq(self, params, req);
1611 }
1612
1613 case EnumerateInstancesReqTag:
1614 {
1615 EnumerateInstancesReq* req = (EnumerateInstancesReq*)msg;
1616 return _HandleEnumerateInstancesReq(self, params, req);
|
1617 mike 1.1 }
1618
1619 case AssociatorsOfReqTag:
1620 {
|
1621 krisbash 1.4 AssociationsOfReq* req = (AssociationsOfReq*)msg;
1622 return _HandleAssociatorsOfReq(self, params, req);
|
1623 mike 1.1 }
1624
1625 case ReferencesOfReqTag:
1626 {
|
1627 krisbash 1.4 AssociationsOfReq* req = (AssociationsOfReq*)msg;
1628 return _HandleReferencesOfReq(self, params, req);
|
1629 mike 1.1 }
1630
|
1631 krisbash 1.4 #ifndef DISABLE_INDICATION
1632
|
1633 mike 1.1 case SubscribeReqTag:
1634 {
|
1635 krisbash 1.4 return _HandleSubscribeReq(self, params);
|
1636 mike 1.1 }
1637
|
1638 krisbash 1.4 #endif /* ifndef DISABLE_INDICATION */
1639
|
1640 mike 1.1 default:
1641 {
1642 /* Unsupported mesage type */
|
1643 krisbash 1.4 trace_DispUnsupportedMessage( self,
1644 params->interaction,
1645 msg,
1646 msg->tag,
1647 MessageName(msg->tag),
1648 msg->operationId );
1649 return MI_RESULT_NOT_SUPPORTED;
|
1650 mike 1.1 }
1651 }
1652 }
|