Skip to content

Instantly share code, notes, and snippets.

@jbratu
Created December 30, 2021 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbratu/62ec16734bc8fe848ded7666a8db896b to your computer and use it in GitHub Desktop.
Save jbratu/62ec16734bc8fe848ded7666a8db896b to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.Threading;
using System.Text;
using System.IO;
namespace ghIPSS_Console
{
class RevCapiWrapper
/// <summary>
/// Summary description for RevCapiWrapper.
/// This Class is an interop wrapper for RevCap32.dll
///
/// 24 March 2005 rjc Created
/// </summary>
{
// Function Prototypes for RevCapi
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevInitializeApi();
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevTerminateApi();
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetApiError();
// The old way to start the engine and open a queue
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevStartLocalEngine(String Pathname, String Database);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevShutdownLocalEngine(byte bSuppressMsg);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevOpenQ(String Qname, String UserName, String Password, out int Queue) ;
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevCloseQ(int Queue);
// The new way to start an engine and open queues
const int REV_CREATE_ENGINE_OPEN_EXISTING = 0 ;
const int REV_CREATE_ENGINE_CREATE_NEW = 1;
const int REV_CREATE_ENGINE_OPEN_ALWAYS = 2;
const int REV_CREATE_ENGINE_INDEXER = 16;
const int REV_CREATE_ENGINE_WAIT_ON_CLOSE = 32;
const int REV_CREATE_ENGINE_NO_UI = 64;
const int UNPROCESSED = 0; // Server has not begun request.
const int PROCESSING = 1; // Server is processing request.
const int DATA_AVAILABLE = 2; // Server has data available.
const int COMPLETED = 3; // Server has completed request, status information is available.
const int PROC_ERROR = 4; // Server process failed, status information is available.
const int INFO_AVAILABLE = 5; // Server has intermediate status information available.
const int INFO_REQUEST = 10 ; // Server is requesting info
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevCreateEngine(String Server,
String Database,
int nFlags,
int nShutdownSessions,
out int Engine);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevCloseEngine( int Engine );
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevCreateQueue( int hEngine ,
String pQueueName,
String pDatabase,
String pUserName,
String pPassword,
out int Queue );
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevCloseQueue( int Queue );
//The rest of the api is the same
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetEngine( int Queue, out int Engine) ;
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetSizeOfQNames();
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetQNames(StringBuilder Buffer,
long buffSize,
char Delimiter) ;
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetSizeOfQStatus(int Queue);
//[ DllImport("REVCAP32.DLL")]
//protected internal static extern int
// RevGetQStatus( int QUEUE, LPQSTATUS As Object)
// ;
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevSetScript( String Script, int ScriptSize);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevSetScriptArg(int PlaceNo, String Value, int dwSize);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevSendScript(int QUEUE, int hTransact, out int Request );
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevSendImm(int Queue, String Script, int ScriptLen, int Transact, int Request, StringBuilder Result);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevSend(int Queue, String Script, int ScriptLen, int Priority, int Transact, out int Request);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevSendArg(int Request, int Position, String Value, int ValueLen) ;
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevEndSend_
(int Request)
;
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevPoll(int Request, out int Status);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevWait(int Request, out int Status);
//[ DllImport("REVCAP32.DLL")]
//protected internal static extern int
// RevWaitEx( int Request, DWORD, DWORD, UINT, UINT, LPINT) ;
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevEndRequest(int Request);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetSizeOfRow( int Request);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetValueOfRow( int Request, StringBuilder Buffer, int BuffSize);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetNumberOfColumns(int Request);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetDataTypeOfColumn(int Request, int ColumnNr);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetSizeOfColumn(int Request, int ColumnNr);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetValueOfColumn(int Request, int ColNo, StringBuilder Buffer, int BuffSize);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetSizeOfStatusText(int Request);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevGetStatusText(int Request, StringBuilder buffer, int bufferSize, char delimiter);
[ DllImport("REVCAP32.DLL")]
protected internal static extern int
RevRespond(int Request, StringBuilder Buffer, int BufferSize);
//
// * End function prototypes *
//
// Fields
private static int m_instanceCount = 0;
// Setting Names
const string WORKING_DIRECTORY = "WorkingDirectory";
const string OESERVER_NAME = "ServerName";
const string DATABASE_NAME = "DatabaseName";
const string CREATE_FLAGS = "CreateFlags";
const string SHUTDOWN_SESSIONS = "ShutdownSessions";
const string QUEUE_NAME = "QueueName";
const string USER_NAME = "UserName";
const string USER_PASSWORD = "UserPassword";
const string PROCEDURE_NAME = "ProcedureName";
// Default values
const string DEFAULT_PROCEDURE_NAME = "RUN_MY_REQUEST";
const string DEFAULT_ENGINE_SECTION = "DefaultEngine";
// Mv Delimiters
const char RM = '\u00FF';
const char FM = '\u00FE';
const char VM = '\u00FD';
// Engine Settings
// The intent is to let you set a section to determine which engine to run
//private static string m_server = "";
private static string m_database = "MYAPP";
private static string m_username = "MYUSER";
private static string m_password = "MYPASSWORD";
private static string m_workingdirectory = "c:\\revsoft\\OINSIGHT";
//private static string m_queue_name = "";
private static int m_create_flags = 1;
private static int m_shutdownsessions = 1;
private static string m_procedure_name = DEFAULT_PROCEDURE_NAME;
//private static int m_engine = 0;
//private static int m_queue = 0;
//private static string m_rowDelim = "\r\n";
private string response = "";
// * end fields *
public RevCapiWrapper()
{
// Default Section
//m_iniSection = DEFAULT_ENGINE_SECTION;
Initialise();
}
public RevCapiWrapper( string SectionName)
{
// Pass in Section
//m_iniSection = "DefaultEngine";
Initialise();
}
private void Initialise()
{
// Get Session Parameters from Ini File
string strTest;
/*
* m_workingdirectory = oIniFile.IniReadValue(m_iniSection, WORKING_DIRECTORY);
* m_server = oIniFile.IniReadValue(m_iniSection, OESERVER_NAME);
* m_database = oIniFile.IniReadValue(m_iniSection, DATABASE_NAME);
* m_username = oIniFile.IniReadValue(m_iniSection, USER_NAME);
* m_password = oIniFile.IniReadValue(m_iniSection, USER_PASSWORD);
*/
//strTest = oIniFile.IniReadValue(m_iniSection, CREATE_FLAGS) ;
strTest = "1";
switch ( strTest)
{
case "0" :
m_create_flags = 2;
break;
case "1" :
m_create_flags = 1;
break;
case "2" :
m_create_flags = 2;
break;
case "64" :
m_create_flags = 64;
break;
case "65" :
m_create_flags = 65;
break;
default:
m_create_flags = 1;
break;
}
//strTest = oIniFile.IniReadValue(m_iniSection, SHUTDOWN_SESSIONS) ;
strTest = "1";
switch ( strTest)
{
case "0" :
m_shutdownsessions = 2;
break;
case "1" :
m_shutdownsessions = 1;
break;
default:
m_shutdownsessions = 1;
break;
}
//strTest = oIniFile.IniReadValue(m_iniSection, PROCEDURE_NAME) ;
strTest = "TEST_ISO8583_MANAGER";
if ( strTest != "" )
{
m_procedure_name = strTest;
}
else
{
m_procedure_name = DEFAULT_PROCEDURE_NAME;
}
// Init Api for the first engine
if ( m_instanceCount == 0 )
{
Environment.CurrentDirectory = m_workingdirectory;
RevInitializeApi();
}
}
~RevCapiWrapper()
{
this.Close();
}
public void Close()
{
//if ( m_queue != 0 )
//{
// RevCloseQueue( m_queue ) ;
// m_queue = 0;
//}
//if ( m_engine != 0 )
//{
// RevCloseEngine( m_engine ) ;
// m_engine = 0 ;
//}
// last engine out kills the api
//m_instanceCount-- ;
//if ( m_instanceCount == 0 )
RevTerminateApi();
}
public string Response
{
get { return response; }
}
public string RunCommand( string strMethod, string request )
{
int lret = 0;
bool bOK = true;
string encoded = base64Encode(request);
response = "";
// bump the engine count
m_instanceCount++;
// set the engine name
// Note: I use the "\\.\pipename" format for the server name
// to get an external, i.e. out of process, engine
// without this you can only start a single engine
string server = "\\\\.\\SK" + m_instanceCount.ToString("00");
string queue_name = "QK" + m_instanceCount.ToString("00");
int queue = 0;
int engine = 0;
//server="8084";
//m_create_flags = 0;
//m_shutdownsessions = 0;
// Is there a queue?
if (bOK)
{
try
{
// Change the current directory.
Environment.CurrentDirectory = (m_workingdirectory);
lret = RevCreateEngine(server, m_database, m_create_flags, m_shutdownsessions, out engine ) ;
if (lret == 0 )
{
lret = RevCreateQueue(engine, queue_name, m_database, m_username, m_password, out queue);
if (lret != 0 )
{
this.Close();
}
}
}
catch ( Exception ex )
{
Console.WriteLine(ex.Message);
lret = -1;
this.Close();
}
}
string strReturnValue = "";
int myStatus = 0;
if ( lret == 0 && bOK)
{
int rowCount = 0 ;
int pollLen = 0;
StringBuilder resultBuffer = new StringBuilder("");
StringBuilder pollBuffer;
string strFuncName = m_procedure_name;
string script = "RUN " + strFuncName + " '" + strMethod + "', " + " '" + encoded + "'";
string statusText = "";
int myRequest = 0;
char chDelim = '\t';
try
{
lret = RevSetScript(script, script.Length);
if (lret == 0)
{
lret = RevSendScript(queue, 0, out myRequest);
}
if (myRequest != 0)
{
do
{
lret = RevPoll(myRequest, out myStatus);
switch (myStatus)
{
case UNPROCESSED: // Server has not begun request.
break;
case PROCESSING: // Server is processing request.
break;
case DATA_AVAILABLE: // Server has data available.
// add break between rows
rowCount++;
//if ( rowCount > 1)
// resultBuffer.Append( m_rowDelim );
int colCount = RevGetNumberOfColumns(myRequest);
int wColNo;
string this_val = "";
for (wColNo = 1; wColNo <= colCount; wColNo++)
{
// Fieldmark between columns
if (wColNo > 1)
resultBuffer.Append(FM);
// Get the data for this columns
pollLen = RevGetSizeOfColumn(myRequest, wColNo);
if (pollLen > 0)
{
pollBuffer = new StringBuilder(pollLen);
lret = RevGetValueOfColumn(myRequest, 1, pollBuffer, pollLen);
this_val = pollBuffer.ToString();
// Append the column
resultBuffer.Append(this_val);
}
}
break;
case COMPLETED: // Server has completed request, status information is available.
// Get the status data
pollLen = RevGetSizeOfStatusText(myRequest);
if (pollLen > 0)
{
pollBuffer = new StringBuilder(pollLen);
lret = RevGetStatusText(myRequest, pollBuffer, pollLen, chDelim);
statusText = pollBuffer.ToString();
resultBuffer.Append(statusText);
}
break;
case PROC_ERROR: // Server process failed, status information is available.
// Get the status data
pollLen = RevGetSizeOfStatusText(myRequest);
if (pollLen > 0)
{
pollBuffer = new StringBuilder(pollLen);
lret = RevGetStatusText(myRequest, pollBuffer, pollLen, chDelim);
statusText = pollBuffer.ToString();
resultBuffer.Append(statusText);
}
break;
case INFO_AVAILABLE: // Server has intermediate status information available.
pollLen = RevGetSizeOfStatusText(myRequest);
if (pollLen > 0)
{
pollBuffer = new StringBuilder(pollLen);
lret = RevGetStatusText(myRequest, pollBuffer, pollLen, chDelim);
statusText = pollBuffer.ToString();
resultBuffer.Append(statusText);
}
break;
case INFO_REQUEST: // Server is requesting info
resultBuffer.Append(statusText);
break;
}
}
while ((myStatus != COMPLETED) && (myStatus != PROC_ERROR));
strReturnValue = resultBuffer.ToString();
}
RevEndRequest(myRequest);
}
catch (Exception e)
{
strReturnValue = " RunRequest Failed ...";
System.Console.WriteLine("{0} \n {1}", strReturnValue, e.Message);
if (myRequest != 0)
RevEndRequest(myRequest);
}
finally
{
if (queue != 0)
{
RevCloseQueue(queue);
queue = 0;
}
if (engine != 0)
{
RevCloseEngine(engine);
engine = 0;
}
//m_instanceCount--;
}
}
return strReturnValue;
}
public bool runRequest(string OiMethod, string request)
{
string encoded = base64Encode(request);
bool isOk = true;
string result = RunCommand(OiMethod, request);
if (isOk)
{
response = base64Decode(result);
}
return isOk;
}
public string base64Encode(string data)
{
try
{
byte[] encData_byte = new byte[data.Length];
encData_byte = System.Text.Encoding.ASCII.GetBytes(data);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
catch (Exception e)
{
throw new Exception("Error in base64Encode" + e.Message);
}
}
public string base64Decode(string data)
{
try
{
System.Text.ASCIIEncoding encoder = new System.Text.ASCIIEncoding();
System.Text.Decoder AsciiDecode = encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(data);
int charCount = AsciiDecode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
AsciiDecode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}
catch (Exception e)
{
throw new Exception("Error in base64Decode" + e.Message);
}
}
}
}
Function TEST_REVCAPI(method)
/*
** Purpose: Test calling revCapi
**
** Usage:
** run TEST_REVCAPI 'SUB' to test callsubroutine
** run TEST_REVCAPI 'FUNC' to test callFunction
** run TEST_REVCAPI '' to test CreateRequest
**
* Notes:
* rjc 12-07-10 Created
*/
Declare Function rti_createGuid
$Insert revcapi_equates
$Insert Msg_Equates
If Assigned(method) Else method = ''
* Connect to an oinsight
serverSpec = "\\.\":rti_createGuid()
databasename = @APPID<1>
flags = 0
shutdownSessions = 0
username = @username
password = @username ;* assume password same as username
queueName = ''
path = drive()
If path[-1,1] = '\' Then path[-1,1] = ''
*
* revCapi will only start an OENGINE
* If don't need to start oi, use startflag = 1 or startflag = 65 for hidden engine
*
* For this example, I want to use Oi.
* That let's you run oipi or windows in the other copy.
* So, launch a child OI using a /sn parameter, then connect to it with startflag = 0
*
*
cmd = "oinsight.exe"
params = ' /sn=':serverspec : ' /ap=' : databasename : ' /un=':username : ' /pw=':password: ' /dv=1'
Call shellExecute(0, 'Open':\00\, cmd:\00\, params:\00\, Drive():\00\, 0)
*
* 15 second delay to allow OI to start
*
elapsed = 0
max_elapsed = 15
loop
started = time()
Loop
Call winyield()
While time() = started
Repeat
elapsed +=1
Call send_Info( 'delay ' : elapsed : ' of ' : max_elapsed : ' seconds')
Until elapsed ge max_elapsed
Repeat
engine = 0
queue = 0
error = 0
returnvalue = ''
statustext = ''
Error = CreateEngine(Engine, ServerSpec, DatabaseName, Flags, ShutdownSessions)
If Not(error) then
Error = CreateQueue(Queue, Engine, QueueName, DatabaseName, UserName, Password)
End
oiFuncName = 'TEST_REVCAPI_SUB'
oiParam = databasename
Begin Case
Case error
Case indexc(method, 'Func', 1)
Call WinYield()
Error = CallFunction(Queue, returnvalue, oiFuncName, oiParam)
Call WinYield()
Case indexc(method, 'Sub', 1)
Call WinYield()
Error = CallSubroutine(Queue, oiFuncName, oiParam)
Call WinYield()
Case 1
script = "RUN " : oiFuncName : " '" : oiParam : "'";
statusText = "";
request = 0;
Status = ''
statusText = ''
returnvalue = ''
this_reply = ''
Error = CreateRequest(request, Queue, Script, '')
if ( request ne 0 ) then
loop
Error = PollForReply(Request, Status)
begin case
case Status eq UNPROCESSED$ // Server has not begun request.
null
case Status eq PROCESSING$ // Server is processing request.
null
case Status eq DATA_AVAILABLE$ // Server has data available.
Error = GetReply(Request, this_reply)
returnvalue := this_Reply
case Status eq COMPLETED$ // Server has completed request, status information is available.
Error = GetStatusText(Request, @vm, StatusText)
case Status eq PROC_ERROR$ // Server process failed, status information is available.
// Get the status data
// Get the status data
Error = GetStatusText(Request, @vm, StatusText)
case Status eq INFO_AVAILABLE$ // Server has intermediate status information available.
this_Text = ''
Error = GetStatusText(Request, @vm, this_Text)
Call send_dyn(this_text)
case Status eq INFO_REQUEST$ // Server is requesting info
this_Text = ''
Error = GetStatusText(Request, @vm, this_Text)
def = ''
def<mType$> = 'RC'
def<mCaption$> = 'Info Needed'
def<mText$> = this_text
ans = Msg(@window, def)
end case
while ( (Status ne COMPLETED$) and ( Status ne PROC_ERROR$) )
repeat
CloseRequest(Request)
end
End case
// Clean Up - close queue and engine. Becuase I used 0 for shutdoen sessions it will not close the OI
//
if queue then x = CloseQueue(Queue)
if engine then x = CloseEngine(Engine)
Call Send_Dyn(' Response = ' : Quote(returnvalue))
Call Send_Dyn(' Status = ' : Quote(statustext))
Call Send_Dyn(' error = ' : Quote(error))
Return ''
Function TEST_REVCAPI_SUB(text)
If Assigned(text) Else text = ''
ans = 'you sent ' : quote(text)
Call Set_Status(1, 'Happy')
Return ans
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment