Document-ID:        17690.1
Subject:            WIN: CREATING USER EXITS FOR FORMS 4.5
Author:             CSHAY
Last Modified Date: 18 December  1996


             Creating a User Exit for Oracle Forms 4.5 on Windows

This bulletin contains additional information that will help you create user
exits for Oracle Forms version 4.5 on Microsoft Windows.

NOTE: This bulletin ONLY applies to Forms 4.5, NOT to any other version.

The sample files referenced in this bulletin should be found in your
C:\ORAWIN\FORMS45\USEREXIT directory.  It is very important that you carefully
examine the following files in that directory: UE_SAMP.PC, UE_XTB.C,
UE_SAMP.MAK, and F45XTB.DEF.

SUPPORTED COMPILER AND PRECOMPILER VERSIONS

You must use the Microsoft Visual C++ compiler version 1.5. This
compiler ships on the Visual C++ 2.0 CD in the MSVC15 directory.  No other
compiler is supported.  If you intend to embed SQL in your user exit you must
use Pro*C 2.0 for Windows.  No earlier version of this precompiler is
supported.

USER EXIT OVERVIEW

All of the user exits you write usually go into one file: F45XTB.DLL.  Forms
will look in \ORAWIN\BIN for this file. If you wish to name this file
differently, split it into pieces, or place it in another directory, please
refer to Chapter 3 of the Forms Advanced Techniques manual. The ORACLE.INI
parameter FORMS45_USEREXITS (plural!) parameter is used for that purpose.
Forms loads F45XTB.DLL, and then looks inside of it for the iapxtb data
structure which you have built into the DLL.  This structure "registers"
your user exit so that Forms knows about it.  Typically, mistakes in building
F45XTB.DLL or bugs in your code will result in Forms being unable to find
your user exit, or more commonly in a General Protection Fault.

USING THE ORA_FFI PL/SQL PACKAGE INSTEAD OF USER EXITS

With Forms 4.5, Oracle has introduced a new way to call a function inside of
a DLL. The PL/SQL package ORA_FFI allows you to call the .DLL directly from
PL/SQL without having to go through the USER_EXIT interface. For more
information on this package, see Chapter 13 of the Forms Advanced Techniques
manual. If you are writing a new application (rather than maintaining an
existing one) you may be interested in this.

STEP ONE: WRITE THE CODE FOR YOUR USER EXIT

Carefully examine the file UE_SAMP.PC and model your user exit after this.  If
you have never written a Windows 3.1 application before, you should not
attempt to build a user exit until you have taken a Windows 3.1 programming
course and can build your own (non-oracle) DLL and call it from your own
Windows executable.  Recomended reading: "Programming Windows 3.1" by Charles
Petzold.

When Forms calls your user exit, it passes you 5 arguments.  The first
argument contains all the arguments passed to your userexit from the trigger
and is a string.  It is up to you to parse this string to get the individual
parameters.  The other 4 parameters can be examined by looking at the uxsql()
function call in UE_SAMP.PC. The meaning of these parameters is summarized
in Chapter 3 of the Forms Advanced Techniques manual.

STEP TWO: REGISTER YOUR USER EXITS

Use the code in the file "UE_XTB.C" as an example of how to properly register
your user exit in the IAPXTB structure (which contains a list of all the user
exits linked in with Oracle Forms).  Here is an example of registering two
user exits:

    #ifndef UE
    #include "ue.h"
    #endif /* UE */

    #include "ue_samp.h"

    /* Define the user exit structure */

    extern exitr iapxtb[] =  {  /* Holds exit routine pointers */
         "USEREXECSQL", uxsql, XITCC,
         "CHECKSTAT", foo, XITCC,
         (char *) 0, 0, 0         /* zero entry marks the end */
    }; /* end iapxtb */

This example associates user exits "USEREXECSQL" and "CHECKSTAT" (the names
that Oracle Forms will use for the user exits) with the C functions "uxsql"
and "foo" respectively.  The third entry on each line of the ipaxtb struct
tells what language the user exit was written in, C in this case (that's what
the "XITCC" means).

To complete this example, you would need to add prototypes for your "uxsql"
and "foo" functions to the file "UE_SAMP.H".

STEP THREE: PRECOMPILE YOUR USER EXIT

NOTE: Do not attempt to use the file "USEREXIT.PRE".  It will not work with
Pro*C 2.0.

The following steps illustrate how to precompile a .PC file and convert it
into a .C file.

  1. Open up the file "UE_SAMP.PC" with a text editor. Under the line
     "#include <stdio.h>" add the following line:

         #include <string.h>

     (This was inadvertently left out of the sample program.)

  2. Start up Pro*C 2.0.

  3. From the menu choose "Edit" then "Add".

  4. Using the file browser, go to \ORAWIN\FORMS45\USEREXIT and select the
     file "UE_SAMP.PC" You should now see "ue_samp.pc" listed under the
     column "Input File"

  5. Use the mouse to click on the filename "UE_SAMP.PC" which will highlight
     it.

  6. Now from the menu choose "Edit" then "Options".  If you don't see this,
     you haven't highlighted the filename.

  7. Under the section labeled "Formatting", set "Input Line Length" to 132
     and "Output Line Length" to 132.

  8. In the box under the heading "Includes Path", type the following:
     "c:\orawin\pro20\c\include\"

  9. If you need to set any other Pro*C options set them now. (This is all that
     is required for UE_SAMP.PC)

  10. Click the "OK" button to dismiss the Options window.
      You should now see the following under the "Options" column:
      "ireclen=132 oreclen=132 include=c:\orawin\pro15\c\"

  11. From the menu choose "File" then "Run" to begin precompiling.

  12. You should see a green check mark in the first column which indicates
      success. If you see a red "X" or yellow check you should click on it to
      see what error you have made.

  13. You will now have created "UE_SAMP.C" in your \ORAWIN\FORMS45\USEREXIT
      directory.

STEP FOUR: TRY BUILDING F45XTB.DLL USING OUR SAMPLE PROJECT

The following steps show how to use the UE_SAMP.MAK file we provide
in building a F45XTB.DLL that contains the sample user exit.

  1. Start up the Visual C++ compiler from Windows (workbench).

  2. From the menu choose "Project", then "Open"

  3. Use the file browser to go to the /ORAWIN/FORMS45/USEREXIT directory and
     choose "UE_SAMP.MAK"

  4. From the menu choose "Options", then "Directories". To the "Include Files
     Path" add:
       "c:\orawin\pro20\c\include;c:\orawin\forms45\userexit"

     To the "Library Files Path" add:
       "c:\orawin\pro20\c\lib;c:\orawin\forms45\userexit"

  5. From the menu, choose "Project" then "Rebuild all". You should get the
     following 2 warnings:

       RC: warning RW4002: Entry point segment 1 set to PRELOAD
       RC: warning RW4002: Non-discardable segment 3 set to PRELOAD

     These are normal. You should not get other errors or warnings.

  6. You have now created UE_SAMP.DLL which will be located in
     \ORAWIN\FORMS45\USEREXIT.

  7. Rename UE_SAMP.DLL to F45XTB.DLL and place it in the \ORAWIN\BIN
     directory (replacing any previous copy of this file).

STEP FIVE: VERIFY THAT THE SAMPLE USER EXIT HAS BEEN BUILT CORRECTLY

The following steps will help you find out whether or not you have done
the previous steps correctly or not.

  1. Launch RUNFORM and select the file "UE_SAMP.FMX"

  2. Click on "UserExit Demonstration"

  3. In the "SQL statement to execute" field, enter:
     "create table uetest (n number)"

  4. You should see the message "Successfully Executed Statement".
     Note: You can only execute one SQL statement per run with this user exit.
     To try another SQL statement you must restart the form.

  5. Shut down the form.

  6. From SQL*Plus, log in as the same user. Do a "select * from uetest"

  7. You should see "no rows selected". If you see a ORA-942 at this point, or
     got any other errors while running the form, the user exit was
     incorrectly built.

STEP SIX: SETTING UP YOUR OWN PROJECT

Before attempting to build your own project, you should first make sure you
can build and run the sample project we provide. (see instructions above).
After successfully doing that, examine the settings we have used in our
project. The only major difference between UE_SAMP.MAK and your own make file
should be that you have included your own version of "ue_xtb.c" and a C file
(or files) similar to "ue_samp.c". In fact, you can simply modify our
ue_samp.mak, removing our ue_xtb.c and replacing it with yours, and removing
ue_samp.c and replacing it with your .C files. Or, you may wish to create a
whole new project from scratch.

The following steps show you in detail how to configure your own project file
from scratch.

  1. From the Menu choose "Project", then "New".

  2. Choose a project name, and choose a project type of "Windows dynamic link
     library".

  3. From the Menu choose "Project", then "Edit".

  4. Use the browser to go to the \ORAWIN\FORMS45\USEREXIT directory and
     highlight each of the following files, then press the button labeled
     "Add": "F45r.LIB","SQL16WIN.LIB", "SQX16WIN.LIB", "OSSWEP.OBJ",
     "UEZ.OBJ", "F45XTB.DEF". You should see each of these 6 files appear in
     the "Files in Project" box.

  5. Use the same browser to locate your .C file(s) that contains your
     userexit (and that you have already precompiled -- in our example this
     was ue_samp.c) and select "Add" for this file(s) as well.

  6. Using the same tecnique, "Add" your modified "ue_xtb.c" file as well.

  7. From the menu choose "Options", then "Project"

  8. Click on "Compiler", then on the "Use Project Defaults" button.

  9. Under "Category" select "PreProcessor".

  10. In the field "Symbols and Macros to define" add the following to what is
      already there: "MSWINDOWS, _WINDLL".

  11. Under "Category", select "Memory Model". Choose "Large" and "SS !=DS, DS
      NOT loaded on function entry", then click OK.

  12. Now click on the "Linker" button. Click on "Use Project Defaults"

  13. Under "Categeory", highlight "Input" and in the "Libraries" field type
      the following library names: "oldnames, libw, ldllcew".  If you don't
      have these libraries, you will need to reinstall your compiler (custom
      install) and choose to install libraries for the Large Memory Model.

  14. Under "Category", highlight "Windows Libraries", then under "Import
      Libraries and DLL's", deselect any of these that you don't specifically
      need. (Generally you can deselect them all.)

  15. Click OK and close all windows.

  16. From the menu choose "Options", then "Directories". To the "Include
      Files Path" add "c:\orawin\pro20\c\include;c:\orawin\forms45\userexit".

      To the "Library Files Path" add:
        "c:\orawin\pro20\c\lib;c:\orawin\forms45\userexit"

  17. From the menu, choose "Project" then "Rebuild all". You should get the
      following 2 warnings:

        RC: warning RW4002: Entry point segment 1 set to PRELOAD
        RC: warning RW4002: Non-discardable segment 3 set to PRELOAD

   These are normal. You should invesitigate any other warnings or errors.

  18. You have now created a .DLL (with the name of your project) which will
      be located in \ORAWIN\FORMS45\USEREXIT.

  19. Rename this DLL to F45XTB.DLL and place it in the \ORAWIN\BIN directory
      (replacing any previous copy of this file).

ANSWERS TO COMMON QUESTIONS ABOUT BUILDING USER EXITS

  o  If you find information in the Online help files, Advanced Techniques
     manual, or Install Guide that differs or contradicts this bulletin,
     please use the information in this bulletin instead.

  o  If you get a FRM-40800 "User Exit Does Not Exist" and you have used the
     parameter FORMS45_USEREXIT in ORACLE.INI, please be advised that the
     actual parameter name is FORMS45_USEREXITS (plural!). This is listed
     incorrectly in the documentation. You should also specify the full (and
     correct) path into your .DLL's when using this parameter to ensure that
     Forms finds them. If you are not using this parameter but are still
     getting this error, you have likely built your user exit incorrectly.
     Follow the steps in this bulletin, using the sample.

  o  User Exits are not supported with Pro*Cobol for Windows.

  o  There is NOT a GENXTB utility available to automatically set up the
     iapxtb.c structure. You have to use the method listed in step 2.

  o  Even though Pro*C 1.5.10 comes with SQL15WIN.LIB and SQX15WIN.LIB,
     and some documentation may refer to these files, you should *not*
     use them when you build user exits. Instead you should use the
     SQL16WIN.LIB and SQX16WIN.LIB that are in your FORMS45/USEREXIT
     directory. These files are discussed in Step 6 above. These 2 files
     should only be used when building user exits. For other non-user exit
     applications you should only use the libraries that came with Pro*C and
     that are documented in the Pro*C installation guide.

  o  If, during precompilation, you get the error:
     "Unable to open include file SQLCA"
     Follow the instructions above in step 3 above to set the "Includes
     Path"

  o  If you get the compile time warnings,
     'strlen' undefined; assuming extern returning int,
     'strcpy' undefined; assuming extern returning int, and
     you haven't included "string.h" to your .PC file.
     (Refer to step 3 above)

  o  If you get these warnings while building the project, please ignore
     them, they are normal:
     Entry point segment 1 set to PRELOAD
     Non-discardable segment 3 set to PRELOAD

  o  If you get an "unresolved external: _sqlca" error when you compile
     UE_SAMP.PC, then change the line "#define SQLCA_STORAGE_CLASS extern"
     in that file to just read "#define SQLCA_STORAGE_CLASS".

  o  If you get an "unresolved external: _sprintf" error when you compile
     UE_SAMP.PC, then add the library LLIBCEW.LIB to your program.