calls.c 11.4 KB
/*
 * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270  e X3270
 * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
 * aplicativos mainframe. Registro no INPI sob o nome G3270.
 *
 * Copyright (C) <2008> <Banco do Brasil S.A.>
 *
 * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
 * os termos da GPL v.2 - Licença Pública Geral  GNU,  conforme  publicado  pela
 * Free Software Foundation.
 *
 * Este programa é distribuído na expectativa de  ser  útil,  mas  SEM  QUALQUER
 * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou  de  ADEQUAÇÃO
 * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
 * obter mais detalhes.
 *
 * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
 * programa;  se  não, escreva para a Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA, 02111-1307, USA
 *
 * Este programa está nomeado como calls.c e possui - linhas de código.
 *
 * Contatos:
 *
 * perry.werneck@gmail.com	(Alexandre Perry de Souza Werneck)
 * erico.mendonca@gmail.com	(Erico Mascarenhas Mendonça)
 *
 */

 #include <windows.h>
 #include <lib3270.h>
 #include <malloc.h>
 #include <string.h>
 #include <errno.h>
 #include <pw3270/hllapi.h>
 #include <stdio.h>
 #include <lib3270/log.h>
 #include "client.h"

 #undef trace
 #define trace( fmt, ... )	{ FILE *out = fopen("c:\\Users\\Perry\\hllapi.log","a"); if(out) { fprintf(out, "%s(%d) " fmt "\n", __FILE__, __LINE__, __VA_ARGS__ ); fclose(out); } }

/*--[ Globals ]--------------------------------------------------------------------------------------*/

 HMODULE 	  hModule	= NULL;
 void		* hSession	= NULL;

 static void			* (*session_new)(const char *model)											= NULL;
 static void			  (*session_free)(void *h)													= NULL;
 static const char		* (*get_revision)(void)														= NULL;
 static int				  (*host_connect)(void *h,const char *n, int wait)							= NULL;
 static int				  (*host_is_connected)(void *h)												= NULL;
 static int 			  (*wait_for_ready)(void *h, int seconds)									= NULL;
 static void 			  (*host_disconnect)(void *h)												= NULL;
 static int 			  (*script_sleep)(void *h, int seconds)										= NULL;
 static LIB3270_MESSAGE	  (*get_message)(void *h)													= NULL;
 static char 			* (*get_text)(void *h, int row, int col, int len)							= NULL;
 static void  			* (*release_memory)(void *p)												= NULL;
 static int  			  (*action_enter)(void *h)													= NULL;
 static int 			  (*set_text_at)(void *h, int row, int col, const unsigned char *str)		= NULL;
 static int 			  (*cmp_text_at)(void *h, int row, int col, const char *text)				= NULL;
 static int				  (*pfkey)(void *hSession, int key)											= NULL;
 static int				  (*pakey)(void *hSession, int key)											= NULL;

 static const struct _entry_point
 {
	void		**call;
	void		* pipe;
	const char	* name;
 } entry_point[] =
 {
	{ (void **) &session_new,		(void *) hllapi_pipe_init,				"lib3270_session_new" 			},
	{ (void **) &session_free,		(void *) hllapi_pipe_deinit,			"lib3270_session_free"			},
	{ (void **) &get_revision,		(void *) hllapi_pipe_get_revision,		"lib3270_get_revision"			},
	{ (void **) &host_connect,		(void *) hllapi_pipe_connect, 			"lib3270_connect"				},
	{ (void **) &host_disconnect,	(void *) hllapi_pipe_disconnect, 		"lib3270_disconnect"			},
	{ (void **) &host_is_connected,	(void *) hllapi_pipe_is_connected, 		"lib3270_in_tn3270e"			},
	{ (void **) &wait_for_ready,	(void *) hllapi_pipe_wait_for_ready, 	"lib3270_wait_for_ready"		},
	{ (void **) &script_sleep,		(void *) hllapi_pipe_sleep, 			"lib3270_wait"					},
	{ (void **) &get_message,		(void *) hllapi_pipe_get_message, 		"lib3270_get_program_message"	},
	{ (void **) &get_text,			(void *) hllapi_pipe_get_text_at, 		"lib3270_get_text_at"			},
	{ (void **) &release_memory,	(void *) hllapi_pipe_release_memory,	"lib3270_free"					},
	{ (void **) &action_enter,		(void *) hllapi_pipe_enter, 			"lib3270_enter"					},
	{ (void **) &set_text_at,		(void *) hllapi_pipe_set_text_at, 		"lib3270_set_string_at"			},
	{ (void **) &cmp_text_at,		(void *) hllapi_pipe_cmp_text_at, 		"lib3270_cmp_text_at"			},
	{ (void **) &pfkey,				(void *) hllapi_pipe_pfkey, 			"lib3270_pfkey"					},
	{ (void **) &pakey,				(void *) hllapi_pipe_pakey, 			"lib3270_pakey"					},

	{ NULL, NULL }
 };

// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx
#ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
	#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS	0x00001000
#endif // LOAD_LIBRARY_SEARCH_DEFAULT_DIRS

#ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
	#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 	0x00000100
#endif // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR

/*--[ Implement ]------------------------------------------------------------------------------------*/

 __declspec (dllexport) DWORD __stdcall hllapi_init(LPSTR mode)
 {
 	if(!mode)
		return EINVAL;

	trace("%s(%s)",__FUNCTION__,(char *) mode);

	if(mode && *mode)
	{
		// Get pointers to the pipe based calls
		int f;

		trace("%s: Loading pipe based calls",__FUNCTION__);
		for(f=0;entry_point[f].name;f++)
			*entry_point[f].call = entry_point[f].pipe;

	}
	else
	{
		// Direct mode, load lib3270.dll, get pointers to the calls
		static const char *dllname = "lib3270.dll." PACKAGE_VERSION;

		int 		f;
		HMODULE		kernel;
		HANDLE		cookie		= NULL;
		DWORD		rc;
		HANDLE 		(*AddDllDirectory)(PCWSTR NewDirectory);
		BOOL 	 	(*RemoveDllDirectory)(HANDLE Cookie);
		UINT 		errorMode;
		char		datadir[4096];

		trace("hModule=%p",hModule);
		if(hModule)
			return EBUSY;

		kernel 				= LoadLibrary("kernel32.dll");
		AddDllDirectory		= (HANDLE (*)(PCWSTR)) GetProcAddress(kernel,"AddDllDirectory");
		RemoveDllDirectory	= (BOOL (*)(HANDLE)) GetProcAddress(kernel,"RemoveDllDirectory");

		// Notify user in case of error loading protocol DLL
		// http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
		errorMode = SetErrorMode(1);

		memset(datadir,' ',4095);
		datadir[4095] = 0;

		if(hllapi_get_datadir(datadir))
		{
			char	buffer[4096];
			wchar_t	path[4096];

			mbstowcs(path, datadir, 4095);
			trace("Datadir=[%s] AddDllDirectory=%p RemoveDllDirectory=%p\n",datadir,AddDllDirectory,RemoveDllDirectory);
			if(AddDllDirectory)
				cookie = AddDllDirectory(path);

#ifdef DEBUG
			snprintf(buffer,4096,"%s\\.bin\\Debug\\%s",datadir,dllname);
#else
			snprintf(buffer,4096,"%s\\%s",datadir,dllname);
#endif // DEBUG

			hModule = LoadLibrary(buffer);

			trace("%s hModule=%p rc=%d",buffer,hModule,(int) GetLastError());

			if(hModule == NULL)
			{
				// Enable DLL error popup and try again with full path
				SetErrorMode(0);
				hModule = LoadLibraryEx(buffer,NULL,LOAD_LIBRARY_SEARCH_DEFAULT_DIRS|LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
			}

			rc = GetLastError();

			trace("%s hModule=%p rc=%d",buffer,hModule,(int) rc);
		}
		else
		{
			hModule = LoadLibrary(dllname);
			rc = GetLastError();
		}
//		hModule = LoadLibraryEx("lib3270.dll.5.0",NULL,LOAD_LIBRARY_SEARCH_DEFAULT_DIRS|LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);

		SetErrorMode(errorMode);

		trace("%s hModule=%p rc=%d",dllname,hModule,(int) rc);

		if(cookie && RemoveDllDirectory)
			RemoveDllDirectory(cookie);

		if(kernel)
			FreeLibrary(kernel);

		if(!hModule)
			return rc;

		// Get library entry pointers
		for(f=0;entry_point[f].name;f++)
		{
			void *ptr = (void *) GetProcAddress(hModule,entry_point[f].name);

			trace("%d %s=%p\n",f,entry_point[f].name,ptr);

			if(!ptr)
			{
				fprintf(stderr,"Can´t load \"%s\"\n",entry_point[f].name);
				hllapi_deinit();
				return ENOENT;
			}
			*entry_point[f].call = ptr;
		}

	}
	// Get session handle
	hSession = session_new((const char *) mode);
	trace("%s ok hSession=%p\n",__FUNCTION__,hSession);

 	return hSession ? 0 : -1;
 }

 __declspec (dllexport) DWORD __stdcall hllapi_deinit(void)
 {
 	int f;

	// Release session
 	if(hSession && session_free)
		session_free(hSession);

	for(f=0;entry_point[f].name;f++)
		*entry_point[f].call = NULL;

 	if(hModule != NULL)
 	{
		FreeLibrary(hModule);
		hModule = NULL;
 	}

 	return 0;
 }

 __declspec (dllexport) DWORD __stdcall hllapi_get_revision(void)
 {
	if(!get_revision)
		return 0;
	return (DWORD) atoi(get_revision());
 }

 __declspec (dllexport) DWORD __stdcall hllapi_connect(LPSTR uri, WORD wait)
 {
 	if(!(host_connect && hSession && uri))
		return EINVAL;

 	return host_connect(hSession,uri,wait);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_is_connected(void)
 {
 	if(!(host_is_connected && hSession))
		return EINVAL;

 	return host_is_connected(hSession);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_disconnect(void)
 {
 	if(!(host_disconnect && hSession))
		return EINVAL;

	host_disconnect(hSession);

	return 0;
 }

 __declspec (dllexport) DWORD __stdcall hllapi_wait_for_ready(WORD seconds)
 {
 	if(!(wait_for_ready && hSession))
		return EINVAL;

	trace("%s seconds=%d\n", __FUNCTION__, (int) seconds);

	return (DWORD) wait_for_ready(hSession,(int) seconds);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_wait(WORD seconds)
 {
 	if(!(script_sleep && hSession))
		return EINVAL;

	return (DWORD) script_sleep(hSession,(int) seconds);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_get_message_id(void)
 {
	if(!(get_message && hSession))
		return EINVAL;
	return (DWORD) get_message(hSession);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_get_screen_at(WORD row, WORD col, LPSTR buffer)
 {
	char	* text;
	int		  len;

	if(!(get_text && release_memory && hSession))
		return EINVAL;

	trace("%s row=%d col=%d buffer=%p",__FUNCTION__,row,col,buffer);
	len = strlen(buffer);

	trace(" len=%d",len);

	text = get_text(hSession,row,col,len);

	trace(" text=%p errno=%d %s\n",text,errno,strerror(errno));

	if(!text)
		return EINVAL;

	strncpy(buffer,text,len);
	release_memory(text);

	trace("text:\n%s\n",buffer);

 	return 0;
 }

 __declspec (dllexport) DWORD __stdcall hllapi_enter(void)
 {
	if(!(action_enter && hSession))
		return EINVAL;

	return (DWORD) action_enter(hSession);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_set_text_at(WORD row, WORD col, LPSTR text)
 {
	if(!(set_text_at && hSession))
		return EINVAL;

	return (DWORD) set_text_at(hSession,row,col,(const unsigned char *) text);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_cmp_text_at(WORD row, WORD col, LPSTR text)
 {
	if(!(cmp_text_at && hSession))
		return EINVAL;

	return (DWORD) cmp_text_at(hSession,row,col,(const char *) text);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_pfkey(WORD key)
 {
	if(!(pfkey && hSession))
		return EINVAL;

	return (DWORD) pfkey(hSession,key);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_pakey(WORD key)
 {
	if(!(pfkey && hSession))
		return EINVAL;

	return (DWORD) pakey(hSession,key);
 }

 __declspec (dllexport) DWORD __stdcall hllapi_get_datadir(LPSTR datadir)
 {
	HKEY 			hKey	= 0;
 	unsigned long	datalen = strlen(datadir);

	*datadir = 0;

	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\pw3270",0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS)
	{
		unsigned long datatype;					// #defined in winnt.h (predefined types 0-11)
		if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) datadir,&datalen) != ERROR_SUCCESS)
			*datadir = 0;
		RegCloseKey(hKey);
	}

	return *datadir;
 }