Recording and Script Generation Services |
Extending API recording requires the writing of a recording component (proxy library) corresponding to the targeted library that implements the functions to be recorded. Traffic between the AUT and target library that is to be recorded passes through the proxy library. The job of the functions in the proxy library is to decide what needs to be recorded and to pass this data to Rational's rtxvutl.dll
, which adds the data to the session file. The proxy library and API Recorder Adapter components must reside in the same DLL.
This chapter documents the calls needed to pass data to rtvutl.dll
. The API recording services are listed below, in the order in which they are used. See Proxy Examples for examples illustrating these calls.
Gets an ID for the specified target DLL.
int ProxyGetAssignedLibraryID(char *DLLName
)
DLLName |
Specifies the name of the target DLL. |
On success, this function returns an ID for the named DLL.
Unlike the other proxy calls, which are called with each write operation, this call is made only during session initialization and so is likely to appear in a different DLL. The returned ID is the libraryID
argument to ProxyLockNew().
This example illustrates the use of this call in an initialization block.
#include <windows.h> #include <tchar.h> #include "SampleAPIWrapper.h" #include "proxutil.h" // initialize global for library ID int gbLibID = 0; int WINAPI DllMain(HANDLE hInstance, ULONG ul_reason_being_called, LPVOID lpReserved) { switch (ul_reason_being_called) { case DLL_PROCESS_ATTACH: { // MUST call the following in DLL_PROCESS_ATTACH // this function is provided by the Utility DLL // rtxutil.dll // the name passed-in must be the exact name of // your wrapper DLL gbLibID = ProxyGetAssignedLibraryID("SampleAPIWrapper.dll"); // add whatever initialization you need here break; } case DLL_PROCESS_DETACH: { // add whatever cleanup you may need here break; } default: { break; } } return 1; }
Gets an ID for a proxy function to be recorded.
DWORD ProxyGetTicket(void)
On success, this function returns the ID uniquely identifying a packet to be recorded. On failure, it returns PROXY_INVALID_TICKET
.
This call begins a write operation inside a proxy function, which should proceed only if the call succeeds. The returned ID is an input argument to ProxyLockNew(). On failure, the correct behavior is to call the real function and return without recording anything.
See Proxy Examples.
Gets a time stamp for a proxy function to be recorded.
DWORD ProxyGetTimeStamp(void)
On success, this function returns the number of milliseconds that have elapsed since the session file was initialized.
This value returned by this function is an argument of ProxyLockNew().
See Proxy Examples.
Locks the session file prior to a write operation.
void *ProxyLockNew (intticketID
, DWORDmsec
, intlibraryID
, intproxyID
, intPacketType
, intpacketSize
)
ticketID |
The ID of the packet to be written to the .wch file. Returned by ProxyGetTicket (). |
msec |
The number of milliseconds elapsed since the session file was initialized. Returned by ProxyGetTimeStamp () |
libraryID |
The ID of the library associated with this proxy call. Returned by ProxyGetAssignedLibraryID() |
proxyID |
The ID of this proxy call. |
packetType |
One of the following:
|
packetSize | The number of bytes to be written. |
The proxyID
is a unique identifier for each function that you record. Typically, you start with 1 and increment proxyID
for each function to be recorded. This argument should be defined in a header file common to the API Recorder, Generator Filter, and API Script Generator adapters, such that the combination of libraryID
and proxyID
uniquely identifies a single proxy function and what it pertains to.
See page74 for an API_SINGLE example; see page75 for an API_ENTRY/API_EXIT example.
Writes a block to the session file.
int ProxyWriteBlock (LPVOID, int
iSize
)
LpData
Pointer to the data to be written to the session file.
iSize
The number of bytes to write.
On success, the function returns the offset from the most recent ProxyLockNew
() call to the beginning of data for the current ProxyWriteBlock
() call.
See Proxy Examples.
Unlocks the session file after a write operation.
void ProxyUnlock (DWORD msec
)
See Proxy Examples.
Returns the library ID and function associated with an error.
void ProxyExceptionHandler (typeproxyLib
, typeproxyFunction
)
proxyLib |
The proxy library ID. |
proxyFunction |
The proxy function ID. |
See Proxy Examples.
To use the proxy utility functions, you must include \Suite\include\proxhdr.h
, whose structures are as follows:
#define API_ENTRY 1 #define API_EXIT 2 #define API_SINGLE 3 /* All three have a common header: */ typedef struct { unsigned char major_type; /* API_ENTRY, API_EXIT, API_SINGLE, WCH_V1 */ unsigned char spare_uchar; /* Future */ unsigned short spare_ushort; /* Future */ unsigned int ticket; /* Unique ticket for each API call */ unsigned int timestamp; /* Entry TS for all but API_EXIT (api return) */ unsigned int total_length; /* Total length of packet including ALL headers */ } major_wch_header; /* API_EXIT has no secondary header */ /* API_ENTRY and API_SINGLE supply the following as a second header: */ typedef struct { unsigned int process_id; /* Process ID of API_proxy */ unsigned int thread_id; /* Thread ID of API_proxy */ unsigned int library_id; /* Library identifier of proxied API */ unsigned int API_id; /* Unique id for each proxied API */ } minor_wch_header; /* API_SINGLE will supply a third header following the second header: */ typedef struct { unsigned int timestamp; /* api return timestamp for API_SINGLE */ unsigned int alignment_uint; /* To maintain double word alignment */ } stamp2_wch_header; /* Packets will be generated for an API_proxy as either a pair of API_ENRTY and API_EXIT sharing a common ticket number OR one API_SINGLE. */
The above structures, including the process ID, thread ID, and total length of the proxy record, are filled in for you automatically.
Following are examples illustrating API_SINGLE and API _ENTRY/API_EXIT. In this examples, pMyProxyFunc()
is the name of the proxy function and RealFunc()
is the name of the actual function in the target DLL that is being recorded.
The following is an API_SINGLE
example.
typedef struct{ int iInput; int iInput2; int dwResult; }MYSTRUCT; LRESULT pMyProxyFunc( int iInput, int iInput2, LPSTR szInString, LPSTR szOutString) { DWORD dwTicket, dwTimeStamp; LRESULT dwResult; MYSTRUCT *pMyStruct; dwTicket = ProxyGetTicket(); if (dwTicket == PROXY INVALID_TICKET) { return RealFunc( iInput, iInput2, szInString, szOutString) } else { dwTimeStamp = ProxyGetTimeStamp(); dwResult = RealFunc( iInput, iInput2, szInString, szOutString) pMyStruct = ProxyLockNew(dwTicket, dwTimeTimeStamp, PROXY_LIB_MY_PROXY, P_MYPROXY_ID, API_SINGLE, sizeof(MYSTRUCT); pMyStruct.iInput = iInput; pMyStructiInput2 = iInput2; pMyStruct.dwResult = dwResult; ProxyWriteBlock(szInString, strlen(szInString) + 1); ProxyWriteBlock(szOutString, strlen(szOutString) + 1); ProxyUnlock(0); return dwResult; } } typedef struct{ int iInput; int iInput2; }MYSTRUCT_IN; typedef struct{ int dwResult; }MYSTRUCT_OUT;
The following is an API_ENTRY/API_EXIT
example.
LRESULT pMyProxyFunc( int iInput, int iInput2, LPSTR szInString, LPSTR szOutString) { DWORD dwTicket, dwTimeStamp; LRESULT dwResult; MYSTRUCT_IN *pMyStructIn; MYSTRUCT_OUT *pMyStructOut; dwTicket = ProxyGetTicket(); if (dwTicket == PROXY INVALID_TICKET) { return RealFunc( iInput, iInput2, szInString, szOutString) } else { dwTimeStamp = ProxyGetTimeStamp(); pMyStructIn = ProxyLockNew(dwTicket, dwTime, PROXY_LIB_MY_PROXY, P_MYPROXY_ID, API_ENTRY, sizeof(MYSTRUCT_IN); ProxyWriteBlock(szInString, strlen(szInString) + 1); ProxyUnlock(0); dwResult = RealFunc( iInput, iInput2, szInString, szOutString) pMyStruct = ProxyLockNew(dwTicket, dwTime, PROXY_LIB_MY_PROXY, P_MYPROXY_ID, API_EXIT, sizeof(MYSTRUCT); pMyStruct.dwResult = dwResult; ProxyWriteBlock(szOutString, strlen(szOutString) + 1); ProxyUnlock(0); return dwResult;
Session Recording Extensibility Reference | Rational Software Corporation |
Copyright (c) 2003, Rational Software Corporation | http://www.rational.com support@rational.com info@rational.com |