取得並呼叫用戶端的匯出方法
下列範例程式碼示範如何取得用戶端匯出的方法清單,以及如何叫用該用戶端的方法。
#include <windows.h>
#include <stdio.h>
#include "Rtmv2.h"
#include "nldef.h"
#include "strsafe.h"
// The following #defines are from routprot.h in the Platform Software Development Kit (SDK)
#define PROTO_TYPE_UCAST 0
#define PROTOCOL_ID(Type, VendorId, ProtocolId) (((Type & 0x03)<<30)|((VendorId & 0x3FFF)<<16)|(ProtocolId & 0xFFFF))
#define PROTO_VENDOR_ID 0xFFFF
// This is the simple callback method the entity (client) first registers and then exports via RtmGetEntityMethods()
void WINAPI Method(RTM_ENTITY_HANDLE CallerHandle, RTM_ENTITY_HANDLE CalleeHandle, RTM_ENTITY_METHOD_INPUT *Input, RTM_ENTITY_METHOD_OUTPUT *Output){
UNREFERENCED_PARAMETER(CallerHandle);
UNREFERENCED_PARAMETER(CalleeHandle);
if(Input != NULL){
wprintf(L"%s\n", Input->InputData);
FillMemory(Output->OutputData,sizeof(ERROR_SUCCESS),ERROR_SUCCESS);
return;
}
FillMemory(Output->OutputData,sizeof(ERROR_INVALID_DATA),ERROR_INVALID_DATA);
return;
}
int __cdecl main(){
RTM_ENTITY_HANDLE ThisClientHandle, OtherClientHandle;
RTM_ENTITY_INFO EntityInfo;
RTM_REGN_PROFILE RegnProfile;
UINT NumMethods = 0;
DWORD dwRet = ERROR_SUCCESS;
PRTM_ENTITY_EXPORT_METHOD ExportMethods = NULL;
RTM_ENTITY_EXPORT_METHODS Methods;
//------------------------------------------------------
// Register a new client with an export method (callback)
//------------------------------------------------------
// Set the callback Method() as the exported client function
Methods.NumMethods = 1;
Methods.Methods[0] = (RTM_ENTITY_EXPORT_METHOD) Method;
// Set the new client's properties
EntityInfo.RtmInstanceId = 0;
EntityInfo.AddressFamily = AF_INET;
EntityInfo.EntityId.EntityProtocolId = PROTO_IP_RIP;
EntityInfo.EntityId.EntityInstanceId = PROTOCOL_ID(PROTO_TYPE_UCAST, PROTO_VENDOR_ID, PROTO_IP_RIP);
// Register the new client in the routing table manager
dwRet = RtmRegisterEntity(&EntityInfo, &Methods, NULL, FALSE, &RegnProfile, &ThisClientHandle);
if (dwRet != ERROR_SUCCESS){
// Registration failed
// Do something here
// clean-up
return 0;
}
//------------------------------------------------------
// Determine the number of exported methods
//------------------------------------------------------
// Calling RtmGetEntityMethods with NumMethods = 0 returns the number of registered methods for the client
// For simplicity in this example, set the caller client handle to be the same as the callee client handle
OtherClientHandle = ThisClientHandle;
dwRet = RtmGetEntityMethods(ThisClientHandle, OtherClientHandle, &NumMethods, ExportMethods);
if (dwRet != ERROR_SUCCESS){
// RtmGetEntityMethods failed
// Do something here
// clean-up
return 0;
}
// If the client registered any methods proceed, otherwise quit
if (NumMethods > 0){
//----------------------------------------------
// Get function pointers to the exported methods
//----------------------------------------------
// Allocate memory from the heap for the number of callback methods registered by the client
ExportMethods = (PRTM_ENTITY_EXPORT_METHOD) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumMethods * sizeof(PRTM_ENTITY_EXPORT_METHOD));
if (ExportMethods == NULL){
// HeapAlloc failed
// Do something here
// clean-up
return 0;
}
// Calling RtmGetEntityMethods in order to receive the callback pointers into ExportMethods
dwRet = RtmGetEntityMethods(ThisClientHandle, OtherClientHandle, &NumMethods, ExportMethods);
if (dwRet != ERROR_SUCCESS){
// RtmGetEntityMethods failed
// Do something here
// clean-up
return 0;
}
//--------------------------
// Call the exported methods using RtmInvokeMethod(). You cannot call the methods directly.
//--------------------------
// Initialize the exported method's input and output data
PRTM_ENTITY_METHOD_INPUT Input;
PRTM_ENTITY_METHOD_OUTPUT Output;
LPWSTR InputString = L"Hello world from the exported method!";
UINT InputSize = sizeof(L"Hello world from the exported method!");
// Allocated heap memory for the method's input data
Input = (PRTM_ENTITY_METHOD_INPUT) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, InputSize + FIELD_OFFSET(RTM_ENTITY_METHOD_INPUT, InputData));
if (Input == NULL){
// HeapAlloc failed
// Do something here
// clean-up
return 0;
}
Input->MethodType = METHOD_TYPE_ALL_METHODS;
Input->InputSize = InputSize;
dwRet = StringCchCopyN((STRSAFE_LPWSTR)Input->InputData, InputSize, InputString, InputSize);
if (dwRet != ERROR_SUCCESS){
// String copy failed
// Do something here
// clean-up
}
// Assume there is no output data for the function other than an error code
// For more than one method, multiply sizeof(DWORD) by the number of exported methods
UINT OutputHdrSize = FIELD_OFFSET(RTM_ENTITY_METHOD_OUTPUT, OutputData);
UINT OutputSize = OutputHdrSize + sizeof(DWORD);
Output = (PRTM_ENTITY_METHOD_OUTPUT) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, OutputSize);
if (Output == NULL){
// HeapAlloc failed
// Do something here
// clean-up
return 0;
}
// Calling RtmInvokeMethod with arbitray input data and output size for the method exported by OtherClientHandle
dwRet = RtmInvokeMethod(ThisClientHandle, OtherClientHandle, Input, &OutputSize, Output);
if (dwRet == NO_ERROR){
// Parse the output from the method
printf("Exported method completed with error code: %d\n", (DWORD) *Output->OutputData);
}
// Clean up: Release handles and free memory
HeapFree(GetProcessHeap(), 0, ExportMethods);
HeapFree(GetProcessHeap(), 0, Output);
HeapFree(GetProcessHeap(), 0, Input);
}
// Clean-up: Deregister the new entity
dwRet = RtmDeregisterEntity(ThisClientHandle);
if (dwRet != ERROR_SUCCESS){
// Deregistration failed
// Do something here
}
return 0;
}