Recording and Script Generation Services

prevnext

Proxy Services Reference


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.

Function Description
ProxyGetAssignedLibraryID() Gets an ID for the specified target DLL.
ProxyGetTicket() Gets an ID for a proxy function to be recorded.
ProxyGetTimeStamp() Gets a time stamp for a proxy function to be recorded.
ProxyLockNew() Locks the session file prior to a write operation.
ProxyWriteBlock() Writes a block to the session file.
ProxyUnlock() Unlocks the session file after a write operation.
ProxyExceptionHandler() Returns the library ID and function associated with an error.


ProxyGetAssignedLibraryID()

Gets an ID for the specified target DLL.


Syntax

int ProxyGetAssignedLibraryID(char *DLLName)


Element Description
DLLName Specifies the name of the target DLL.


Return Value

On success, this function returns an ID for the named DLL.


Comments

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().


Example

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;
}

ProxyGetTicket()

Gets an ID for a proxy function to be recorded.


Syntax

DWORD ProxyGetTicket(void)

Return Value

On success, this function returns the ID uniquely identifying a packet to be recorded. On failure, it returns PROXY_INVALID_TICKET.


Comments

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.


Example

See Proxy Examples.


ProxyGetTimeStamp()

Gets a time stamp for a proxy function to be recorded.


Syntax

DWORD ProxyGetTimeStamp(void)

Return Value

On success, this function returns the number of milliseconds that have elapsed since the session file was initialized.


Comments

This value returned by this function is an argument of ProxyLockNew().


Example

See Proxy Examples.


ProxyLockNew()

Locks the session file prior to a write operation.


Syntax

void *ProxyLockNew (int ticketID, DWORD msec, int libraryID, 
int proxyID, int PacketType, int packetSize)


Element Description
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:
  • API_ENTRY. Begin a record in a badly written API that overwrites input data parameters.

  • API_EXIT. End a record.

  • API_SINGLE. Produce a single record for each proxy function.

Normally specify API_SINGLE. If used, API_ENTRY and API_EXIT must both be used in order to get a complete record.
packetSize The number of bytes to be written.


Comments

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.


Example

See page74 for an API_SINGLE example; see page75 for an API_ENTRY/API_EXIT example.


ProxyWriteBlock()

Writes a block to the session file.


Syntax

int ProxyWriteBlock (LPVOID, int iSize)

element Description
LpData Pointer to the data to be written to the session file.
iSize The number of bytes to write.


Return Value

On success, the function returns the offset from the most recent ProxyLockNew() call to the beginning of data for the current ProxyWriteBlock() call.


Example

See Proxy Examples.


ProxyUnlock()

Unlocks the session file after a write operation.


Syntax

void ProxyUnlock (DWORD msec)


Element Description
msec Specify as 0 for the default behavior, described below:
  • API_SINGLE. ProxyGetTimestamp() is called and the result placed in the session file header.

  • API_ENTRY and API_EXIT. The original time stamp passed with ProxyLock is placed in the session header.

Alternatively, you can enter a number of milliseconds to place in the session header.


Example

See Proxy Examples.


ProxyExceptionHandler()

Returns the library ID and function associated with an error.


Syntax

void ProxyExceptionHandler (type proxyLib, type proxyFunction)


Element Description
proxyLib The proxy library ID.
proxyFunction The proxy function ID.


Example

See Proxy Examples.


Proxy Data Types

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.


Proxy Examples

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;

prevnext


Session Recording Extensibility Reference Rational Software Corporation
Copyright (c) 2003, Rational Software Corporation http://www.rational.com
support@rational.com
info@rational.com