This chapter describes the use of the TUXEDO System/T /Workstation for Microsoft Windows, Version 3.0 and later.
This instantiation offers significant benefits to the application developers:
The major sections in this chapter cover:
System/T terms are defined in the BEA TUXEDO Glossary but we have extracted terms specific to this feature:
The TUXEDO System/Workstation for Windows runs on Intel 80286 processors and above.
The machine on which the /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 TUXEDO System/T and the
native-side /Workstation installed.
This section covers items specific to writing and building TUXEDO System/T 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 the chapter "Buffers" in the BEA TUXEDO Administrator's Guide and the tuxtypes(5) manual page.
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 System/T 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:
for tperrno or tpurcode -- #include "atmi.h" for Ferror -- #include "fml.h" for Uunixerr -- #include "Uunix.h" for proc_name -- #include "userlog.h"
See Figure 2 for an example.
LPSTR szRplyMax; long wCurrRplyMax = 0; /* Current value of 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 MSC.MAK - Microsoft C makefile
These are the files needed to produce a bankapp client for Windows. Notice there are two make files, MSC.MAK, if you use the Microsoft C compiler and
Take a look through the application file, BANKAPPW.C; we want to call your attention to a few items. Figure 2 shows the #include files you should include.
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 Figure 3 shows, you declare your FBFR as a FAR pointer. In Windows NT FAR and PASCAL are defined to be nothing. Figure 3 also shows that you write your client program as a WinMain() module.
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 Figure 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 figure also shows a call to tpsetunsol.
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 Figure 5) of how syntax errors cause a message to be displayed on the user's screen by means of a call to MessageBox.
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. Figure 6 shows the beginning of this section of the code.
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 Figure 7 shows how errors might be handled. In lines 391-392, for example, the 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.
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 TUXEDO System 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(3) AEWsetblockinghook(3) in the BEA TUXEDO Reference Manual: Section 3c.
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(3) AEWsetblockinghook(3), which allows the programmer to define a special routine which 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 System/T 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.
TUXEDO System/T clients can be build without using the buildclt(1) utility. If the Microsoft Visual C++ projects are used then set the Preprocessor options to
-D_TM_WIN
for Windows 3.x
-DWIN32
for Windows 95. In the linker options add
WTUXWS.LIB
to the input libraries for Windows 3.x and
WTUXWS32.LIB MSVCRT.LIB
for Windows 95. In addition to this set the INCLUDE, LIB and
PATH search directories appropriately.
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 /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
When you run client programs, your PATH must include %TUXDIR%/bin.
The following is a list of limitations that apply to Release 5.0 (and higher) of the System/T Windows DLL.