/*++ Copyright (c) 1997 - 98, Microsoft Corporation Module Name: rtmmetd.c Abstract: Contains routines that deals with invocation of methods that entities export to other entities for the purpose of interpreting entity specific data. Author: Chaitanya Kodeboyina (chaitk) 22-Aug-1998 Revision History: --*/ #include "pchrtm.h" #pragma hdrstop DWORD WINAPI RtmGetEntityMethods ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ENTITY_HANDLE EntityHandle, IN OUT PUINT NumMethods, OUT PRTM_ENTITY_EXPORT_METHOD ExptMethods ) /*++ Routine Description: Retrieves the set of methods exported by a given entity. Arguments: RtmRegHandle - RTM registration handle for calling entity, EntityHandle - RTM handle for entity whose methods we want, NumMethods - Number of methods that can be filled is passed in, and number of methods exported by this entity is returned, ExptMethods - Set of methods requested by the caller. Return Value: Status of the operation --*/ { PRTM_ENTITY_EXPORT_METHODS EntityMethods; PENTITY_INFO Entity; DWORD Status; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); VALIDATE_ENTITY_HANDLE(EntityHandle, &Entity); EntityMethods = &Entity->EntityMethods; // // Does the caller just need number of methods ? // if (*NumMethods == 0) { *NumMethods = EntityMethods->NumMethods; return NO_ERROR; } // // Check if we have space to copy all methods // if (EntityMethods->NumMethods > *NumMethods) { Status = ERROR_INSUFFICIENT_BUFFER; } else { Status = NO_ERROR; *NumMethods = EntityMethods->NumMethods; } // // Copy as many methods as u can fit in output // ASSERT(ExptMethods != NULL); CopyMemory(ExptMethods, EntityMethods->Methods, *NumMethods * sizeof(RTM_ENTITY_EXPORT_METHOD)); *NumMethods = EntityMethods->NumMethods; return Status; } DWORD WINAPI RtmInvokeMethod ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ENTITY_HANDLE EntityHandle, IN PRTM_ENTITY_METHOD_INPUT Input, IN OUT PUINT OutputSize, OUT PRTM_ENTITY_METHOD_OUTPUT Output ) /*++ Routine Description: Invokes a method exported by another entity Arguments: RtmRegHandle - RTM registration handle for calling entity, EntityHandle - Handle for entity whose method we are invoking, Input - Input buffer with the following information - Methods to be invoked, - Common Input buffer to all these methods, OutputSize - Size of the output buffer is passed in, and the number of bytes filled in output is retd, Output - Output buffer that is filled in the format of a series of (Method Id, Corr. Output) tuples Return Value: Status of the operation --*/ { PRTM_ENTITY_EXPORT_METHODS EntityMethods; PENTITY_INFO Entity; DWORD MethodsCalled; DWORD MethodsLeft; UINT OutputHdrSize; UINT OutBytes; UINT BytesTotal; UINT BytesLeft; UINT i; BytesTotal = BytesLeft = *OutputSize; *OutputSize = 0; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); // // Validate the entity and target handles passed in // VALIDATE_ENTITY_HANDLE(EntityHandle, &Entity); // // Call each method in 'methods to be called' mask. // MethodsCalled = MethodsLeft = Input->MethodType; ACQUIRE_ENTITY_METHODS_READ_LOCK(Entity); if (Entity->State == ENTITY_STATE_DEREGISTERED) { RELEASE_ENTITY_METHODS_READ_LOCK(Entity); return ERROR_INVALID_HANDLE; } OutputHdrSize = FIELD_OFFSET(RTM_ENTITY_METHOD_OUTPUT, OutputData); EntityMethods = &Entity->EntityMethods; for (i = 0; (i < EntityMethods->NumMethods) && (MethodsLeft); i++) { // // Do we have bytes left for next method's output ? // if (BytesLeft < OutputHdrSize) { break; } // // If next method in list, prepare input and invoke // if (MethodsLeft & 0x01) { Input->MethodType = Output->MethodType = (1 << i); Output->OutputSize = BytesLeft - OutputHdrSize; // // Initialize the output params of this method // Output->OutputSize = 0; Output->MethodStatus = ERROR_NOT_SUPPORTED; // // If method supported, invoke with input/output // if (EntityMethods->Methods[i]) { EntityMethods->Methods[i](RtmRegHandle, EntityHandle, Input, Output); } OutBytes = Output->OutputSize + OutputHdrSize; Output = (PRTM_ENTITY_METHOD_OUTPUT) (OutBytes + (PUCHAR) Output); BytesLeft -= OutBytes; } MethodsLeft >>= 1; } RELEASE_ENTITY_METHODS_READ_LOCK(Entity); Input->MethodType = MethodsCalled; *OutputSize = BytesTotal - BytesLeft; return NO_ERROR; } DWORD WINAPI RtmBlockMethods ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN HANDLE TargetHandle OPTIONAL, IN UCHAR TargetType OPTIONAL, IN DWORD BlockingFlag ) /*++ Routine Description: Blocks or unblocks the execution of methods on the target handle or on all targets if the target handle is NULL. Arguments: RtmRegHandle - RTM registration handle for calling entity, TargetHandle - Destination, Route or NextHop Handle TargetType - Type of the TargetHandle (DEST_TYPE, ...) BlockingFlag - RTM_BLOCK_METHODS or RTM_RESUME_METHODS to block, unblock method invocations resp. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); UNREFERENCED_PARAMETER(TargetType); UNREFERENCED_PARAMETER(TargetHandle); #if DBG // // No method locks on the target used at present // if (ARGUMENT_PRESENT(TargetHandle)) { PVOID Target; VALIDATE_OBJECT_HANDLE(TargetHandle, TargetType, &Target); } #endif if (BlockingFlag == RTM_BLOCK_METHODS) { ACQUIRE_ENTITY_METHODS_WRITE_LOCK(Entity); } else { RELEASE_ENTITY_METHODS_WRITE_LOCK(Entity); } return NO_ERROR; }