Generator Filter Adapter API |
If you extend API recording, you must provide a Generator Filter Adapter (GFA). GFAs are listed on the Generator Filtering tab of the Session Record Options dialog box, by the name you specify with GetDisplayName()
. Each GFA is associated with a single Script Generator Adapter (SGA), whose name is returned by GetScriptgenDllName(). When a user selects a GFA and starts the AUT, recording of traffic between it and the target DLL commences. The role of the GFA is to direct recorded information packets that are relevant to script generation to the SGA.
Generator Filter Adapters implement the following calls. The shaded rows list functions that other adapter types also implement.
Identifies a Generator Filter Adapter.
BOOL IsAPIGenFiltExtAdapter
();
Return TRUE to indicate that this is a Generator Filter Adapter. Any other response disables the adapter.
This response identifies an adapter as a Generator Filter Adapter:
extern "C"
BOOL LINKDLL IsAPIGenFiltExtAdapter
()
{
return TRUE;
}
IsAPIRecorderAdapter()
, IsAPISgenAdapter()
Returns the name of the associated API Script Generator Adapter.
intGetScriptgenDllName
(TCHAR *name
, size_tnameSize
);
When a user selects this Generator Filter Adapter from the Generator Filtering tab, the API Script Generator Adapter named with this call is also selected.
This example specifies that the API Script Generator Adapter to be used with this adapter is named APISGenAdapterSample.dll
.
extern "C"
int LINKDLL GetScriptgenDllName
(TCHAR *name, size_t nameSize)
{
TCHAR buf[] = "APISGenAdapterSample.dll";
if (_tcslen(buf) >= nameSize
return RSR_BUFFER_TOO_SHORT;
else
{
_tcscpy(name, buf);
return RSR_SUCCESS;
}
}
Checks for scriptable packets.
intCheckAPIPacket
(void *packet
, intIDNum
, int *NextConn
, int *clientIP
, int *clientPort
, int *serverIP
, int *serverPort
);
The session controller presents all recorded functions in the session file to all Generator Filter Adapters. Your adapter inspects the packets and determines which are relevant for script generation. Multiple passes through the session file can be made.
Every packet of data received by your adapter has a controller-assigned "next available" connection number, NextConn
. You return each packet to the session controller as follows:
NextConn
of 0.
NextConn
ID. This ID is now an "existing connection," as this term is used in the next bullet. When the session controller receives this packet, it designates the packet for forwarding and increments NextConn
.
NextConn
ID.
See Sample API Generator Filter Adapter.
GetScriptgenDllName()
,
PassComplete()
,
ProcessAPIPacket()
Returns the public name of this adapter.
intGetDisplayName
(TCHAR *name
, size_tnameSize
);
name |
Pointer to a container for the adapter's display name. Copy the name to this location. |
nameSize |
INPUT. The size allocated for name . The adapter's display name cannot exceed this size. |
Specify the GUI name for this adapter. This is the name (protocol) that is displayed on the Generator Filtering dialog.
This example specifies that the protocol name associated with this adapter is MyAPIProtocol
.
extern "C"
int LINKDLL GetDisplayName
(TCHAR *name, size_t nameSize)
{
TCHAR buf[] = "MyAPIProtocol";
if (_tcslen(buf) > nameSize)
return RSR_BUFFER_TOO_SHORT;
_tcscpy(name, buf);
return RSR_SUCCESS;
}
Returns configuration options in effect for this adapter.
intGetOptions
(TCHAR *options
, size_toptionsSize
);
As illustrated in the example, options supported by an adapter should be entered from a saved, local file. Otherwise, they do not persist between sessions.
Your adapter can define a custom format for options and provide a custom GUI for displaying and editing them and code to communicate the user's choices to the adapter. Do not include custom-format options in your response to this call.
The following table describes the Robot-defined configuration option arguments that a Generator Filter Adapter can support. See Adapter Configuration on page 81 for a mapping of these options to the Robot GUI.
The following response indicates that this adapter supports a single custom configuration triplet:
extern "C"
int LINKDLL GetOptions
(TCHAR* options, size_t optionsSize)
{
TCHAR buf[RSR_MAX_OPTIONS];
_tcscpy(buf, _T(""));
_tcscat(buf, CONFIGURATION);
_tcscat(buf, _T(",Password,system,Enter server password"));
_tcscat(buf, _T(";"));
if (_tcslen(buf) > optionsSize)
return RSR_BUFFER_TOO_SHORT;
_tcscpy(options, buf);
return RSR_SUCCESS;
}
Sets user-specified configuration options for this adapter.
intSetOptions
(TCHAR *options
, size_toptionsSize
);
options |
INPUT. Pointer to a read-only location containing the Robot user's selections. |
optionsSize |
INPUT. The size of options . |
When the user selects a Robot-defined option or edits an adapter-defined option, this call communicates the user's choice to your adapter.
This call also returns a user's choices for adapter-defined options, in the triplet format, that were selected from a Robot-provided dialog. However, if you use a custom GUI for displaying and editing custom options, you are responsible for reading the dialog, conveying the user's choices to the adapter, parsing, validation, and sending an appropriate error message for invalid user specifications.
This example checks to see whether a Robot user selected the Think maximum (ms) option.
extern "C"
int LINKDLL SetOptions
(TCHAR* options, size_t optionsSize)
{
/* CStringArray declared for parsed sub-strings */
CStringArray OptionsArray;
/* parse the original string with semi-colon delimeter.*/
ParseString(options,';',&OptionsArray);
for(int i = 0;i<OptionsArray.GetSize();i++)
{
/* for every sub-string, create another CStringArray*/
CStringArray SubArray;
if(!OptionsArray.GetAt(i).IsEmpty())
{
/*parse the substrings with comma delimeters */
ParseString (OptionsArray.GetAt(i).GetBuffer
(OptionsArray.GetAt(i).GetLength()),',',&SubArray);
/* deal with each sub-string set */
if(SubArray[0]==GENERATOR_THINK)
{
if(SubArray[1] == 0)
{
int think_min = SubArray[2];
}
else
{
/* Unrecognized option -- error may be thrown*/
}
}
}
}
Provides a custom GUI for adapter-defined configuration options.
intDisplayCustomConfigGUI
(TCHAR *errorMessage
, size_terrorMessageSize
);
If your adapter specifies the option CONFIGURATION,USE_CUSTOM_UI
, a Configure button on the Generator per Protocol tab of the Session Record Options dialog is enabled. If a user clicks this button, Robot issues this call. In response, your adapter should display a custom GUI for entering or editing custom configuration options.
GetOptions()
, and the options need not adhere to the triplet format defined by Robot for custom options.
GetOptions()
, the Robot user can use a provided triplet grid as well as your custom GUI.
GetOptions()
. Doing so causes an error because the format is not understood.
SetOptions()
. With a custom GUI, you are responsible for reading and persisting user choices.
extern "C" int LINKDLLDisplayCustomConfigGUI
(TCHAR *errorMessage
, size_terrorMessageSize
) { //display custom GUI and gather user input if (successful) return RSR_SUCCESS; else { TCHAR buf[] = "Custom GUI failed to start"; if (_tcslen(buf) > errorMessageSize) return RSR_BUFFER_TOO_SHORT; _tcscpy(errorMessage, buf); return RSR_FAILURE; } }
The following sample is part of the extended example described in API Example.
////////////////////////////////////////////////////////////////////// // Copyright (c) Rational Software Corporation. 2001 // All Rights Reserved. // // FILENAME: APIFilteringAdapterSample.c // DESCRIPTION: implementation of Sample "APIFilteringAdapterSample" // // REVISION HISTORY // PROGRAMMER DATE REVISION // ====================================================================== // // DJM 05/25/01 initial version // ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Includes ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// #include <windows.h> #include <tchar.h> // Rational headers #include "ExtDefs.h" #include "proxhdr.h" #include "psystem.h" #include "plibdefs.h" // local #include "APIFilteringAdapterSample.h" static unsigned int uiLibID = 0; char buf2; #define RSR_EXT_STUB_SILENT "RSR_EXT_STUB_SILENT" ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Function Definitions ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// BOOL IsAPIGenFiltExtAdapter() { return TRUE; } int GetDisplayName(TCHAR* name, size_t nameSize) { TCHAR buf[] = "MyAPIProtocol"; if (_tcslen(buf) < nameSize) { _tcscpy(name, buf); if(!GetEnvironmentVariable(RSR_EXT_STUB_SILENT,&buf2,0)) MessageBox(NULL, "get Display name called and succeeded", "DJM filter adapter", MB_OK); return RSR_SUCCESS; } else { return RSR_ERROR; } } int GetScriptgenDllName(TCHAR* name, size_t nameSize) { TCHAR buf[] = "APISGenAdapterSample.dll"; //if (_tcslen(buf) < nameSize) //{ _tcscpy(name, buf); if(!GetEnvironmentVariable(RSR_EXT_STUB_SILENT,&buf2,0)) MessageBox(NULL, name, "filter, DJM getscriptgenname", MB_OK); return RSR_SUCCESS; /*} else { return RSR_ERROR; }*/ } int GetOptions(TCHAR* options, size_t optionsSize) { TCHAR opVar[4096]; _tcscpy(options, _T("")); if (GetEnvironmentVariable(_T("RSR_FILTER_OPTIONS"), opVar, 4096) != 0) { _tcscpy(options, opVar); return RSR_SUCCESS; } _tcscat(options, "options;options"); if (_tcslen(options) >= optionsSize) return RSR_BUFFER_TOO_SHORT; else return RSR_SUCCESS; } int SetOptions(TCHAR* options, size_t optionsSize, TCHAR* errorMsg, size_t errorMsgSize) { return RSR_SUCCESS; } int DisplayCustomConfigGUI(TCHAR* errorMessage, size_t errorMessageSize) { return RSR_SUCCESS; } int CheckAPIPacket(void* packet, int IDNum, int* NextConn, int* clientIP, int* clientPort, int* serverIP, int* serverPort) { major_wch_header *majorhdr; char buf[MAX_PATH]; majorhdr = packet; // this example doesn't pass any packet type besides API_SINGLE // on to the script generator if (majorhdr->major_type == API_SINGLE) { minor_wch_header *minorhdr = (minor_wch_header *)((char*)packet + sizeof(major_wch_header)); // I'm interested in the following packet types switch (IDNum) { // add filters for other libraries here case PROXY_LIB_WINDOWS_SYSTEM: // check all the customer adapter records // to see if it is ours if (minorhdr->API_id != P_CUSTOMADAPTER_A) { *NextConn = 0; } else { // custom adapter record, let's // see if it is ours S_CUSTOMADAPTER *custadapter = (S_CUSTOMADAPTER *)((char*)packet + sizeof(major_wch_header) + sizeof(minor_wch_header) + sizeof(stamp2_wch_header)); void *p = (void *)((char*)packet + sizeof(major_wch_header) + sizeof(minor_wch_header) + sizeof(stamp2_wch_header) + custadapter->iOffszLibraryName); char *szLibName = (char *)p; /* wsprintf(buf, "sizeofmajor=%d sizeofminor=%d", sizeof(major_wch_header), sizeof(minor_wch_header)); MessageBox(NULL, buf, "DJM Filter", MB_OK); wsprintf(buf, "szOffset=%d", custadapter->iOffszLibraryName); MessageBox(NULL, buf, "DJM Filter", MB_OK); MessageBox(NULL, szLibName, "DJM Filter", MB_OK); MessageBox(NULL, "custadapterpacket found", "DJM filter adapter", MB_OK); */ if (stricmp(szLibName, "SampleAPIWrapper.dll") == 0) { uiLibID = custadapter->uiLibID; MessageBox(NULL, szLibName, "Identified System library record", MB_OK); //wsprintf(buf, "lib ID=%d", uiLibID); //MessageBox(NULL, buf, "DJM lib id", MB_OK); } else *NextConn = 0; } break; default: // check for any records that are to be thrown away //wsprintf(buf,"default processing libID=%d looking for uiLibID=%d",IDNum, uiLibID); //MessageBox(NULL,buf,"DJM non sys packet", MB_OK); if (IDNum != (int)uiLibID) *NextConn = 0; if (uiLibID == 0) *NextConn = 0; if (IDNum == (int)uiLibID) { wsprintf(buf,"processing with good data packet conn number=%d looking for uiLibID=%d", *NextConn, uiLibID); MessageBox(NULL,buf,"DJM Filter", MB_OK); //MessageBox(NULL, "found packet to process", "DJM Filter", MB_OK); } break; } } else { *NextConn = 0; } return RSR_SUCCESS; }
Session Recording Extensibility Reference | Rational Software Corporation |
Copyright (c) 2003, Rational Software Corporation | http://www.rational.com support@rational.com info@rational.com |