This chapter describes the use of the BEA TUXEDO Workstation for Microsoft Windows, Version 3.0 and later.
This instantiation offers significant benefits to the application developers:
What This Chapter Is About
The major sections in this chapter cover:
BEA TUXEDO system terms are defined in the BEA TUXEDO Glossary, but we have extracted terms specific to this feature:
Definitions of Terms, Acronyms, and Abbreviations
This section lists the hardware and software prerequisites.
The BEA TUXEDO Workstation for Windows runs on Intel 80286 processors and above.
The machine on which the BEA TUXEDO Workstation is installed runs as a remote machine to a UNIX server.
Workstation for Windows runs under the Windows Version 3.0 or later operating system.
In Windows while using TCP/IP any Windows Sockets Compliant TCP/IP stack can be used. The Windows DLL has been tested with the NOVELL LAN WorkPlace for MS-DOS using the Windows Sockets interface.
In Windows 95 the native TCP/IP stack is used.
The UNIX server machine must have the BEA TUXEDO system and the native-side BEA TUXEDO Workstation installed.
This section covers items specific to writing and building BEA TUXEDO client programs to run under Microsoft Windows. They are intended to supplement the material presented in the BEA TUXEDO Programmer's Guide.
For information on defining application-specific buffers types for the Windows environment, please see Administering the BEA TUXEDO System and tuxtypes
(5) in the BEA TUXEDO Reference Manual.
Our assumption is that readers of this section either have experience in writing Windows programs or have access to tutorial material on that subject. Our discussion is limited to a description of how you go about putting BEA TUXEDO Workstation functions into Windows modules.
The ATMI and FML calls used in Windows client programs are much the same as described in the BEA TUXEDO Programmer's Guide. They must, however, be incorporated into Windows modules. The following things work slightly differently than they do in the UNIX environment.
.h
files. To make them available in client programs:
for tperrno or tpurcode -- #include "atmi.h"
for Ferror -- #include "fml.h"
for Uunixerr -- #include "Uunix.h"
for proc_name -- #include "userlog.h"
See Listing 5-2 for an example.
tpsetunsol
MakeProcInstance()
to create a "thunk" pointer. Both the .DEF
file and the .C
file must include the definition. This step is required under Windows 3.x.
See Listing 5-4 for an example.
tuxgetenv
(3) and tuxputenv
(3) have been created for this purpose. An example is given in Listing 5-1; the reference pages are in the BEA TUXEDO Reference Manual.
Listing 5-1 Handling the Environment
LPSTR szRplyMax;
long wCurrRplyMax = 0; /* Current value of BEA TUXEDO Reply buffer
* in memory
*/
....
if(szRplyMax = tuxgetenv((LPSTR)"WSRPLYMAX") == NULL)
wCurrRplyMax = 0L;
else
wCurrRplyMax = atol(szRplyMax);
if(wCurrRplyMax 10240L) {
if(tuxputenv("WSRPLYMAX=16384") == 0)
wCurrRplyMax = 16384L;
}
Among the files in the directory $TUXDIR/apps/ws
you will find the following.
BALANCE.DLG - dialog resource for BANKAPPW BALANCE window
BANKAPPW.C - Windows application
BANKAPPW.DEF - Windows definition file for BANKAPPW
BANKAPPW.RC - Windows resource file for BANKAPPW
BANKAPP.H - BANKAPPW window field identifiers
BANKFLDS - FML buffer field identifiers
NT.MAK - Microsoft C makefile
These are the files needed to produce a bankapp
client for Windows.
Take a look through the application file, BANKAPPW.C
; we want to call your attention to a few items. Listing 5-2 shows the #include
files you should include.
Listing 5-2 bankapp for Windows:#
include Files
15 #include stdio.h>
16 #undef NULL
17 #include windows.h>
18 #include stdlib.h>
19 #include string.h>
20 #include ctype.h>
21 #include atmi.h>
22 #include Usysflds.h>
23 #include fml.h>
24 #include userlog.h>
25 #include "bankapp.h"
26 #include "bankflds.h"
The #undef NULL
at line 16 is there to prevent a compiler warning caused by NULL
being defined in both stdio.h
and windows.h
.
At line 45, as Listing 5-3 shows, you declare your FBFR
as a FAR
pointer. In Windows NT FAR
and PASCAL
are defined to be nothing. Listing 5-3 also shows that you write your client program as a WinMain()
module.
Listing 5-3 bankapp for Windows: WinMain Declaration
44 static HANDLE hInst;
45 static FBFR FAR *fbfr;
46
47 int PASCAL
48 WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
49 HANDLE hInstance;
50 HANDLE hPrevInstance;
51 LPSTR lpCmdLine;
52 int nCmdShow;
In Listing 5-4 there are examples of the statements needed to declare a routine to pick up unsolicited messages. The statement must be in both the .C
file and the .DEF
file. The example also shows a call to tpsetunsol
.
Listing 5-4 bankapp for Windows: Declaring Unsolicited Message Routine
In BANKAPPW.C
40 BOOL FAR PASCAL CloseDlg(HWND, WORD, WORD, LONG);
41 BOOL FAR PASCAL OpenDlg(HWND, WORD, WORD, LONG);
42 void FAR PASCAL UnsolProc(char FAR *, long, long);
.
.
.
167 lpfnCloseDlg = MakeProcInstance(CloseDlg,hInst);
168 lpfnOpenDlg = MakeProcInstance(OpenDlg,hInst);
169 lpfnUnsolptr=MakeProcInstance((FARPROC)UnsolProc,hInst);
170
171 if(tpsetunsol((void FAR*)lpfnUnsolptr) == TPUNSOLERR)
172 userlog("tpsetunsol failed");
In BANKAPPW.DEF
16 EXPORTS WndProc
17 TransferDlg
18 BalanceDlg
19 DepositDlg
20 WithdrawDlg
21 CloseDlg
22 OpenDlg
23 UnsolProc
Lines 183 to 325 are Field Validation Routines: five routines that check the validity of the input typed in by the user. We will not show this code except for an example (in Listing 5-5) of how syntax errors cause a message to be displayed on the user's screen by means of a call to MessageBox
.
Listing 5-5 bankapp for Windows: Displaying a Syntax Error
203 if (i 5 || i > 6 || account[i] != '\0') {
204 /*SetDlgItemText (hDlg, item, ""); */
205 MessageBox (hDlg,
206 "Account number must be 5 or 6 digits",
207 "BANKAPP", MB_OK);
208 SetFocus(GetDlgItem(hDlg, item));
209 return(-1);
The actual work of the application begins at with the comments at line 354 describing six dialog boxes. Listing 5-6 shows the beginning of this section of the code.
Listing 5-6 bankapp for Windows: Dialog Boxes
354 /*
355 * Routines to handle dialog boxes for Services
356 * BalanceDlg(hDlg, message, wParam, lParam)
357 * CloseDlg(hDlg, message, wParam, lParam)
358 * DepositDlg(hDlg, message, wParam, lParam)
359 * OpenDlg(hDlg, message, wParam, lParam)
360 * TransferDlg(hDlg, message, wParam, lParam)
361 * WithdrawDlg(hDlg, message, wParam, lParam)
362 */
363 BOOL FAR PASCAL
364 BalanceDlg(hDlg, message, wParam, lParam)
365 HWND hDlg;
366 WORD message;
367 WORD wParam;
368 LONG lParam;
The dialog boxes, which take up the rest of the code, accept input from the user, start a transaction (assuming -Dtran
is specified when the client is built), make a call to the requested service and return information to the user. The code in Listing 5-7 shows how errors might be handled. In lines 391-392, for example, the call to tpbegin
fails, a message is sent to userlog
(3c) and also to the user's screen via the string account1
. In lines 397-403, if the service call fails and the buffer is not NULL, the status line is picked up and returned to the user. If the failure is due to another reason or if the buffer is NULL, a hard-coded error message is returned.
Lines 416-417 show the service request being successfully performed and the requested balance being displayed on the user's screen.
Listing 5-7 bankapp for Windows: Error Handling
390 #ifdef tran
391 if (tpbegin(30, 0) == -1) {
392 (void) userlog("failed to begin transaction\n");
393 lstrcpy(account1, "Transaction failed");
394 }
395 else
396 #endif
397 if (tpcall("INQUIRY", (char FAR *)fbfr, 0,
(char FAR *FAR *)&fbfr, &len, 0) == -1) {
398 if(tperrno== TPESVCFAIL && fbfr != NULL &&
399 (s=Ffind(fbfr,STATLIN,0,0)) != 0) {
400 lstrcpy(account1, s);
401 }
402 else
403 lstrcpy(account1,"Inquiry failed");
404 #ifdef tran
405 (void) tpabort(0);
406 #endif
407 }
408 else {
409 #ifdef tran
410 if(tpcommit(0) < 0) {
411 lstrcpy(account1, "Inquiry failed");
412 }
413 else
414 #endif
415
416 wsprintf(account1, "Account Balance: %s",
417 (LPSTR) Ffind(fbfr, SBALANCE, 0, 0));
418 }
When an ATMI function is called the Windows DLL could block on the network waiting for a reply from the server on the UNIX machine. This can happen on any call that initiates a network message to the UNIX machine, for example, tpcall()
, tpinit()
, tpgetrply()
and so on. These functions may take an arbitrary long time to complete; a good example is tpcall()
, which may block until the server has completed the processing required.
Windows 3.x is not a preemptive multitasking operating system and there is only one system wide Windows input queue. Because of this if a client program blocks on the network, the entire Windows interface "freezes" until the network call returns.
With the BEA TUXEDO Workstation for Windows a blocking operation that cannot be completed immediately is handled as follows. The DLL initiates the operation and enters a loop in which it dispatches any windows messages (yielding the processor to another thread if necessary) and then checks for the completion of the ATMI function. If the ATMI call is complete the blocking call is completed and the appropriate result is returned to the caller. If not complete the DLL continues to dispatch Windows messages. For a complete description of this behavior see AEWsetblockinghook
(3c) in the BEA TUXEDO Reference Manual.
If a Windows message is received for a process for which a blocking operation is in progress, there is a risk that the application will attempt to issue another ATMI call. Such application behavior is not supported by ATMI calls. AEWisblocked
(3c) can be called at any time to detect if there is a blocking ATMI call outstanding. Any other ATMI call made while this condition exists will fail and set tperrno
to TPEPROTO
.
Although this mechanism is sufficient for simple applications, it cannot support the complex message dispatch requirements of more advanced applications (for example, those using the MDI (Multiple Document Interface) model). For such applications, ATMI includes AEWsetblockinghook
(3c), which allows the programmer to define a special routine that will be called instead of the default routine.
If an application invokes a blocking operation like tpcall()
and provides a typed buffer to it as an argument, it is the responsibility of the application to ensure that the buffer is available to ATMI until the operation is completed.
FML functions will continue to work even if there is a blocking call in progress, therefore it is the responsibility of the application to not use FML buffers that are passed in as an argument to an ATMI call that is currently in progress until the ATMI call completes.
As Workstation for Windows 3.x starts up it copies the environment from the Windows area to a local buffer and maintains a distinct environment space for each client. The local space is destroyed when tpterm()
is called. It is the responsibility of the application to reinstate the environment and other information installed using tpsetunsol()
and AEWsetblockinghook()
after tpterm()
is called.
For Windows any compiler that can read Microsoft C import libraries can be used.
When compiling BEA TUXEDO client programs for Windows 3.x, use the C preprocessor flag
-D_TM_WIN
When link editing your client programs, use buildclt
(1) with the -W
flag.
BEA TUXEDO clients can be built without using the buildclt
(1) utility. If the Microsoft Visual C++ projects are used then set the Preprocessor options as follows.
-D_TM_WIN
WTUXWS.LIB
to the input libraries.
WTUXWS32.LIB
MSVCRT.LIB
to the input libraries.
In addition to this set the Windows Version 3.x (16 bit) recommends that C programs use "structure packing" on a one byte boundary. With the Microsoft C compiler this is enabled using the When you run client programs, your The following is a list of limitations that apply to Release 5.0 (and higher) of the BEA TUXEDO system Windows DLL:
INCLUDE
, LIB
, and PATH
search directories appropriately.
Using views in 16-bit Windows
/Zp
option. The view compiler viewc
uses the Microsoft C compiler to calculate the offsets of the C structures. In order for viewc
to use the structure packing and get the correct offsets, set the CFLAGS
variable to /Zp
before running viewc
. As an example if the client C program uses structure packing on a one byte boundary then compile the C code as follows.
CL /Zp -D_TM_WIN CLIENT.C
and before compiling the views
set CFLAGS=/Zp
VIEWC.EXE CLVIEW.V Runtime
PATH
must include %TUXDIR%/bin
.
Limitations