Sat, Apr
5 New Articles

The Distributed Program APIs

  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

With no fanfare whatsoever, IBM introduced a major new API set for the Windows client of Client Access/400. This set, collectively known as the Distributed Program APIs, is available with the System Object Access function. Simply stated, the APIs let you develop programs on the PC that can directly call programs on the AS/400, passing and receiving parameter values.

This is a radical innovation, and potentially will help you develop client/ server programs much more quickly than using other APIs. Because you can directly call an AS/400 program, you don’t need to code special communications code, as with the APPC APIs, or include data queue handling when using the data queue APIs. In fact, if you have AS/400 functions already split out into subprograms—for example, a tax calculation routine that is in a separate program—you should be able to call those programs directly from your PC program. The Distributed Program APIs can help you create client/server programs more quickly than other methods because you can use the AS/400 programs that you already have.

How to Get the APIs

You get the Windows DLL that provides the API functions when you install System Object Access (SOA). You can order SOA as a PTF package (SF21273 for licensed program 5763-XC1), or install SOA from the Client Access/400 refresh that is scheduled for release soon. If you order the PTF, you need to specify DELIVERY(*ANY). The PTF package will be sent to you on tape because the package is too large to be sent over ECS. (See the May/June 1995 issue of PCSE for a review of other functions in SOA, “System Object Access - Application or API?”)

When you install SOA, a subdirectory called SOASPGMS is created in your CAWIN directory. The SOASPGMS directory contains sample programs and source

code for running the SOA programs. The file that you want to look at is EHNDPW.H, the C header file for the Distributed Program-Windows APIs. The header file contains some documentation for the APIs, constants used with the APIs, and function declarations for each of the APIs.

In addition to the header file, file EHNDPW.DLL is installed in the CAWIN directory. The DLL file contains the executable code for each of the APIs. The DLL can be used with any PC language that supports the C calling convention. The APIs in EHNDPW.DLL can only be used by Windows programs.

API Functions Provided

There are 25 user-accessible functions within EHNDPW.DLL. These functions are divided into three groups.

System Functions are used to create a connection between the PC program and the AS/400. When you use the system functions, you start a server job on the AS/400 that processes your program call requests. You also end the server job using a system function API.

The Program Functions group contains APIs to define the program that will be called, work with parameters for the program, call the program, and get information about the program and parameters.

Finally, the Message Functions group helps you get messages and information about messages that are sent as a result of errors when calling the program.

As with any API set, it makes sense to learn about the APIs by looking at how they’re used, rather than by proceeding through the APIs alphabetically. There is a specific sequence that you’ll need to use when calling a program with the APIs. You’ll also find that you only need to use a subset of the APIs to get started.

Getting Started with the APIs

To get started with the APIs, you’ll first want to print file EHNDPW.H, the C header file. Even if you plan to use a PC language other than C, you’ll need to examine this file to learn about the APIs, the parameters used on the functions, and the return code values that you might encounter. Later in this article, I’ll tell you how to get an equivalent file of function declarations that you can use with Visual Basic.

EHNDPW.H starts with notes about how the APIs are used. If you are accustomed to working with PC languages, the concepts and program flow will probably be easy to grasp. However, if most of your experience is as an RPG programmer, you might find it difficult, at first, to understand how the APIs are used. With an RPG program, you customarily include a CALL statement, followed by PARM statements. The Distributed Program APIs define the parameters first, then call the program. I’ll explain this in more detail later.

After the initial documentation, EHNDPW.H continues with definitions for constants. The first set of constants is used to define the maximum number of parameters, and the parameter types. You can call an AS/400 with up to 25 parameters.

Parameter types can be defined as input, output, or input/output. These types provide options that are different from the way an AS/400 programmer customarily uses parameters. In an RPG, COBOL, or CL program, all parameters are input/output, as values can be passed and returned through any parameter (i.e., if you call an AS/400 program from another AS/400 program, the called program can change a parameter, and the change is reflected back to the caller).

The input and output parameter types are used extensively with the APIs themselves. An input parameter is passed from the calling program to the called program. Any changes to the parameter are not returned to the caller. An output parameter is in the parameter list of the calling program; however, any value that you set in the calling program is not passed to the called program. The called program can change the value of the output parameter. The changed value is available to the calling program upon return from the called program.

To call existing AS/400 programs, you might want to consider defining the parameters as input/output, as that provides the same type of parameter usage available with AS/400 languages. You’ll need to examine existing code carefully to see if you can define parameters as simple input or output parameters.

The next set of constants in EHNDPW.H is used to define message types. These constants are used with the Message Functions API group. For example, you can test a message to determine if it is a completion, diagnostic, notify, or escape message.

The final set of constants define return codes from the API functions. These are in four general groups: the OK return code, meaning that the API functioned correctly; communications return codes (e.g., no connection to system); program errors (e.g., program not found, too many/ too few parameters); and environment errors (e.g., invalid window, system, or program handle). As with any API, you should, at a minimum, check for the OK return code. If the return code is not OK, you can then go to a generic error handling routine, or you can branch to specific error handling depending on the type of return code.

The Function Declarations

After the constants, EHNDPW.H begins the function declarations. The declarations are listed by function group (i.e., system, program, message), and roughly in order by usage within the groups.

Each API function declaration starts with a synopsis that includes the name of the API, a brief description of it, then a list of the parameters used with the API. Although the synopsis includes a reference for return codes, none of the APIs currently have any documented return codes. You should be able to examine the return code constants and determine which ones will apply to an API. You can also test each API individually to discover the return codes that you might encounter (e.g., call a nonexistent program to discover the return code that you get in that situation).

The function declarations are standard C syntax and formatting. Windows conventions are used for the data type and variable names.

All of the Distributed Program functions start with the character string “EHNDP_”. The second part of the function name is descriptive of the function. For example, the EHNDP_StartSys API is used to start the conversation with the AS/400.

If you work with C, you should find the function declarations to be straightforward. But even if you’re unfamiliar with C, or don’t use C as your primary programming language, you should spend some time reading through the declarations. You’ll want to know the functions that are available, their names, and the parameters used with each function.

The Distributed Program API Tester Program

I created a test program in Visual Basic to learn about the Distributed Program APIs. Figure 1 shows the dialog that is presented when the program is run. The program uses six command buttons to run Distributed Program functions. The Visual Basic

program calls an AS/400 CL program, passing parameters to it. The CL program sends a message to the QSYSOPR message queue, displaying the parameters. The CL program finishes by moving a value into a parameter. The return value is obtained with a Distributed Program API and placed into the message list box shown in the figure. The code for these programs is too long to include with this article, but you can get it with the Visual Basic function declaration file. Even without the code, we can examine the flow of the Tester program, which I feel is representative of the flow that you would use for production programs. The Tester demonstrates the initialization and cleanup work you’ll need to do, and also how to define parameters, put values into them, call the AS/400 program, and extract the value for returned parameters.

Before stepping through the details of the program, we need to get an overview of processing flow, as it relates to using the Distributed Program APIs.

Sequence and Flow of the APIs

I mentioned earlier that using the Distributed Program APIs is not quite the same as the AS/400 CALL/PARM construct. There are several additional steps that you need to take before issuing the program call. You need those additional steps because you must create the proper environment for the program call. You then need to provide details about each of the parameters you’re going to use. After actually calling the program, you retrieve the parameters that contain return values. When you’re finished, you close the environment that you created for the APIs.

Before you can use the Distributed Program APIs, you need a router connection to the AS/400 where the program that you want to call is located. Your first step with the Distributed Program APIs is to start a connection to the system. You then “create” a program, which means that you identify the program you’re going to call. After creating the program, you can add up to 25 parameters to it. As with any AS/400 program, the parameters must match those on the called program.

At that point, you can call the AS/400 program. Assuming that you’ve correctly defined the parameters and have a working connection, the AS/400 program will run. The called program must be batch oriented; you cannot call an AS/400 program that uses display file I/O.

When the AS/400 program returns or ends, you then call Distributed Program APIs to retrieve the parameter values. Unlike standard AS/400 programs, where values for all of the parameters are available to the calling program when the called program returns, you specifically have to retrieve the value from each parameter in which you’re interested.

At this point, you can call the same or another program. You already have the connection environment, so you don’t need to start the system again. If you’re calling a different program, you need to create the program and add parameters to it. If you’re recalling a program that you’ve already created and added parameters to, you can use an API to set the value of the parameters for a subsequent call.

When you’re done working with the AS/400 programs, you “delete” the program, which removes it from your PC environment. Finally, you stop the system, which means that your connection with the AS/400 is dropped (not the router, just the Distributed Program connection to the server program).

At any point during your calling sequence, you may need to use the APIs that obtain information about the environment. After calling an API, you will need to check the return code. If the call was unsuccessful, you may need to call the message handling

APIs to retrieve the AS/400 error messages. The message handling APIs provide functions equivalent to the program message queue handling operations on the AS/400.

I’ll explain what happens when you click each of the command buttons on the Tester. When you obtain the source code and run the program, you’ll find it useful to step through the program and set breakpoints.

The Start System Function

Before you can call an AS/400 program with the Distributed Program API, you have to start a connection to the AS/400. This connection is between your PC program and an AS/400 server job. This connection presumes that you have an active router connection to the AS/400.

If you attempt to start the program connection without having an active router session, the start attempt fails.

You start the program connection with the EHNDP_StartSys (StartSys) API. Figure 2 shows the details of this API. StartSys uses four parameters. The first, hWnd, is the handle to the window that the program is associated with. This is standard Windows programming practice. hWnd is the first parameter of all of the Distributed Programming APIs, so I won’t describe it again from this point on.

The second parameter is the name of the system with which you want to start the connection. This is one of the systems to which you have a router connection. As with other Client Access APIs, you can pass a null value for this parameter, in which case the default system is used.

The third parameter is the application name. This is supposed to be a unique identifier for the application you’re starting. A null value is allowed for this parameter. The application name is not used in any of the other Distributed Program APIs, so its purpose is unclear.

The last parameter is a return value, the handle to the system. This is a very important value, as it is used with other Distributed Program APIs to point the APIs to the correct system. For example, if you start connections to two systems within the same PC program, you need to use StartSys for each system. You’ll get a unique handle for each system, which then identifies that system. As with any handle, you must never alter its value. You just use the value that is passed back from the API. The value has no meaning as far as your application is concerned; it is used internally by the APIs.

When you use StartSys, two jobs are started in the QCMN subsystem. The first job starts program QLZPSERV. I couldn’t determine the functions performed by this job, in relation to the Distributed Program APIs. The second QCMN job starts program QIWS/QZRCSRVR. This program is the actual server processor, which handles Distributed Program requests from your PC program. This job uses ICF file QIWS/QCZRCICF to communicate with the PC. Examining this job shows that APPC is being used to communicate from the PC program to the AS/400 program. However, we’re insulated from the low-level APPC programming required for communications between the two machines. This is one of the main advantages of the Distributed Program APIs.

If you used a null value for the system name on StartSys, you can find out the name of the system used with the EHNDP_GetSysName (GetSysName) API. The API is described in Figure 3. If you explicitly passed a system name, there would be no point to call this API because you’d already know the name of the system. But if you’re creating general-purpose programs that might run with different AS/400s, you might need to use the null system name value on StartSys, then use GetSysName to get the default

name. You could also use EHNAPPC_GetDefaultSystem from the APPC API, but GetSysName ensures that you get the system name that applies to the StartSys API usage.

GetSysName uses three parameters. The second is the handle to the system that was returned from StartSys. The third is the name of the system that the connection was started to.

Figure 1 shows the result of clicking the Start System command button. The message list box at the top of the figure contains messages that I formatted after calling the APIs. After calling each API, I check for a return code of EHNDP_OK, meaning that the API completed successfully. If the return code is not OK, I go to an error message formatting routine. For some APIs, such as the StartSys API, I include additional information on normal completion. In this example, I’m displaying the hex value of the system handle returned by StartSys. I include a separator line between each API, as shown in the figure. After clicking each command button, you can review the additional messages by scrolling through the message list box. I can’t show you the entire sequence of messages in the list box, so I won’t describe them any more in this article. Just be aware of the function when you run the sample program.

The Create Program Function

Contrary to what you make think from its name, the EHNDP_CreatePgm (CreatePgm) API does not create a program on the AS/400 in the way that a CRTxxxPGM command does. Instead, the CreatePgm API creates a program object in your PC memory. That object is used to identify the actual program that you want to call on the AS/400, and serves as a connection between your PC and the actual AS/400 program. Figure 4 shows the parameters used with CreatePgm.

If most of your programming experience is in the AS/400 environment, you’ll want to take the time to be clear on how the terminology used with this API differs from the AS/400 terminology. The API uses the verb “create” and the noun “object,” which AS/400 programmers instinctively associate with a program object being created from source.

As you can see from Figure 4, what you’re really creating with this API is a handle to a named program. This is all done in the PC memory. When you run this API, there is no communication flow to the AS/400. The API does not verify that you supplied a valid library and program name. If you used incorrect values (e.g., you specified a program name that doesn’t exist), you won’t find out about it until you actually call the program.

You need to run this API to get the handle assignment. After getting the handle to the program, you’ll need to add parameters to the program using the handle. Finally, you can call the program.

I haven’t yet experimented with special or NULL values for the library name parameter. The QCMN communications entry that handles the program evoke request when the program is called specifies a default user value of *SYS. The user profile used to start the router is associated with the server job that processes the request, so the library list for the user is available to the job. I presume that special values like *LIBL are supported for the library name parameter on this API.

After calling the CreatePgm API, you have a handle to the system where the program is located, and a handle to the program object that you’re going to call. That takes care of establishing the environment for the program. You now need to add parameters to the program before calling it.

The Add Parameter Function

Unlike the AS/400 CALL/PARM construct, you define your parameters before issuing the call. You define parameters with the EHNDP_AddParm (AddParm) API, shown in Figure 5.

When you use AddParm, what you’re really doing is reserving space in your PC memory. This space is simply a sequence of 1 to n bytes. You specify how many bytes to reserve for the parameter. When you use AddParm, a pointer to that space is set, and the parameter count is incremented. The pointers and parameter count are associated with the program that you’re going to call, by the program handle value that was returned in CreatePgm.

AddParm uses a parameter to specify the type of parameter, which has nothing to do with the field characteristics (string or numeric and length). The type of parameter is input, output, or input/output. If you’re an AS/400 programmer, you’ll probably be most comfortable defining all of the parameters as input/output, as that provides an equivalent to how AS/400 programs call each other. As you become more familiar with the Distributed Program APIs and processes, you might want to refine your parameter type usage.

This is actually a pretty interesting process, under the covers. The way this process works, it appears that there is a mechanism within the AS/400 server to add parameters dynamically to a program call. This differs from the usual AS/400 programming practice, where you hard-code the number of parameters into your AS/400 source programs. Now, for sure, the AS/400 has always had such a built-in parameter handling mechanism because it has to resolve the number of parameters when one AS/400 program calls another. Here, we have access to this parameter list building process.

Unlike AS/400 programs, you don’t specify the type of parameter, but only the length of the parameter. For character string fields, you can simply use the length of the string. For numeric fields, you’ll have to be careful to match the expected parameter in the AS/400 program. For packed fields, which are the default in CL programs and RPG programs unless defined differently, you need to calculate the number of bytes required to hold the field and the sign half-byte. For example, if a CL program parameter variable is DEC(5,0), you’ll need a parameter length of 3 on the AddParm API (two and a half bytes used for the five digits, one-half byte for the sign). If the parameter is DEC(6,0), you need a parameter length of 4.

If you’ve defined the numeric field explicitly as zoned or binary, then you need to specify the number of bytes required to hold the field.

In my testing, I found numeric parameters to be particularly troublesome. This is because of the parameter length consideration, and also because the values need to be converted from ASCII to packed, zoned, or binary, then back, when returning to the PC program. The conversion functions are in the Data Transform API (EHNDT). They are not particularly easy to use in Visual Basic, as you need to work with pointers to the values. The sample program includes an example of ASCII-to-Packed conversion.

As with any call to an AS/400 program, you must supply the right number of parameters, and values for numeric parameters must be valid. For example, if your AS/400 has three parameters, you can’t just concatenate all of the values in your PC program and pass one parameter that’s as long as all three. You need to pass three corresponding parameters. If you don’t pass valid numeric values, you’ll get MCH-type error messages when your called program on the AS/400 references the parameter. Based on the experience I had with the Distributed Program APIs, you’ll want a program like Tester to experiment with parameter passing.

The Call Program Function

After defining your parameters, you use the EHNDP_CallPgm (CallPgm) API to actually call the AS/400 program from your PC program. Looking at the function definition in Figure 6, you can see that this API is almost anticlimactic. That’s because you’ve done all of the set-up work before issuing the call. The API simply references the handles of the system and the program that were created earlier. The parameter list is from the AddParm API calls that you did before using this API.

As with AS/400 program-to-program calls, this is where the action and the problems start. You’ll run into the usual problems, such as the program not being found, authority problems, incorrect parameters, and so on. Upon return to your PC program, you absolutely must check the return code from the CallPgm API before you even think of using any other Distributed Program APIs. If the return code is anything other than EHNDP_OK, you had a problem. You can use the message function APIs to retrieve the messages sent from the AS/400, and possibly determine what the cause of the failure was (chances are that the system operator will also get messages on the AS/400, and you’ll have a job log from the failed job to work with).

The Distributed Program APIs include two APIs that relate to the “call mode” of the program. The default call mode is synchronous, meaning that while the called AS/400 program is processing, your PC program is locked. The EHNDP_SetCallMode API lets you set the call mode to asynchronous, meaning that you can call the AS/400 program, then resume your PC program while waiting for the called program to return. The EHNDP_GetCallMode API retrieves a value that lets you determine the current mode being used.

I didn’t see any documentation about how this feature works, but I suspect that Windows call-back processing is used. If so, Visual Basic programs are limited to synchronous mode, unless third-party VBXs or custom controls that provide call-back support are obtained. I did not test the SetCallMode API; all of my tests were done with the default, synchronous call mode.

My feeling is that this should not present too much of a problem. If you’re going to use existing AS/400 modules, chances are that those modules are already working with interactive programs. In that case, when you call the module from an AS/400 program, you are, in effect, working in synchronous mode anyway. Your response time should be comparable to an AS/400-to-AS/400 program call, meaning that it should be tolerable, especially after the first call. If you find response time of synchronous calls to be an issue, and you’re working with Visual Basic (no call-back support), you might need to consider alternative methods of “submitting” work and then checking for a response, such as data queues.

The Get Parm API

At this point, you have all of the APIs you need to call an AS/400 program and pass parameters to it. Although useful, you probably also want to receive parameters back. To do that, you’ll need to use the EHNDP_GetParm (GetParm) API, shown in Figure 7.

You need to call GetParm for every parameter for which you want to retrieve a value. That’s because you don’t have a parameter list, as in an RPG program; you can’t just refer to values. Even though you added the parameter earlier with the AddParm API, you need to use GetParm. Think about what’s happening: the AS/400 program has returned, and written the parameter values out. You didn’t directly call the AS/400 program; you used the server program on the AS/400 as your intermediary.

Because the server program doesn’t have hard-coded knowledge of how many parameters you’re working with, you have to request those parameters from the server with the GetParm API. When you use GetParm, the parameter values are retrieved from the server program and written to your PC memory, where you can then reference them.

GetParm is tricky to use, especially in Visual Basic, because the returned parameter is a pointer to a pointer. You’ll need to use either the EHNDT_MemCopy API or the Windows lstrcpy function to copy the returned parameter from the memory location indicated by the pointer to a buffer (string) that you can use in Visual Basic.

Another consideration with GetParm is that you reference the parameter you want by relative order in the parameter list. You need to refer to the parameter by number because there are no field names associated with the returned parameter list, as in an RPG program. The list is zero-based, meaning that the first parameter is identified as parameter zero, the second parameter in the list is identified as parameter one, and so on.

Another API that you might need to use is EHNDP_GetParmCount (GetParmCount), shown in Figure 8. This API returns a value that indicates the number of parameters in the list. Using GetParmCount, you might be able to create a generic parameter retrieval routine in your PC program, looping through GetParm for the number of parameters from GetParmCount. The alternative is simply hard-coding GetParm code for each parameter.

After you retrieve the parameters that you can work with (in Visual Basic you have to move them to a buffer), you’ll need to do some additional work before you can use the value. For character string values, you’ll need to do an EBCDIC to ASCII translation. For numeric parameters, you’ll need to use the appropriate Data Transform API to convert from packed, zoned, or binary to an ASCII numeric value. This can be tedious and error-prone coding. You’ll probably want to run some test cases, then create wrapper functions that you can simply include in your production programs.

The Delete Program API

When you’re done calling the AS/400 program, you should call the EHNDP_DeletePgm (DeletePgm) API to remove the program object from your PC memory. Doing so will free up the memory for other purposes. The DeletePgm API does not delete the program object on the AS/400.

Figure 9 shows the DeletePgm API parameters. After you call this API, you can no longer use the CallPgm API for the same program handle. You would have to use CreatePgm again to create a new handle and program object.

You can call DeletePgm at any point after creating the program handle. For example, if your application only needs to call an AS/400 program once for initialization purposes, there’s no point to keeping the program object constructs in PC memory after the initialization.

The Stop System API

When you’re done calling AS/400 programs from your PC program, you’ll want to call the EHNDP_StopSys (StopSys) API, shown in Figure 10. Calling this API terminates the conversation with the server program on the AS/400. If you neglect to call this API, the server program remains active.

After calling this API, the handle to the system that was created in the StartSys API is no longer usable. If you want to call AS/400 programs again, you need to go through the entire process, starting with StartSys.

If you started conversations to multiple systems, you need to run StopSys for each system. Conversely, you can use StopSys for one system, but continue to use active conversations to other systems.

Other APIs

In this article, I have not shown or described many other APIs. Figure 11 shows the names of those APIs and briefly describes them.

In the Tester program, I use several of the Message Function APIs to retrieve error messages from the AS/400.

Distributed Program Versus Other Techniques

As exciting as the Distributed Program API suite is, you need to consider where it fits in with other Client Access/400 APIs and techniques. It is true that this suite provides the equivalent function that AS/400 programmers have used for years: the capability of calling one program from another, and passing parameters between the programs. However, that technique has always had built-in limitations.

For example, say that you want to create a server program that you’ll call to read records from a file. You don’t know how many records each call will return; it could be from zero to many. It’s tricky to write such a server, and fill up an arbitrary buffer with records. I know; I’ve created a system that uses such servers. In this case, it might be better to use an APPC or a CPI-C program, or a data queues program, to receive the file processing request, then fill a buffer that is external to the program. For example, APPC and CPI-C “send” operations will fill a communications buffer that the system manages. With data queues, you simply write a data queue entry for each record. The system manages the buffer. Your receiving program has a far easier job because it can simply retrieve one entry at a time from the buffer or queue.

On the other hand, you probably have a number of routines already coded that you’ve been using for years in your production systems. If you’ve been careful to create stand-alone modules, you can probably call those modules from your Windows programs. This will help you quickly develop a Windows equivalent to the AS/400 program because you don’t have to recreate the logic that is available in the existing modules.

There is no limitation on using any of these techniques exclusively in a program. You might find that you use both the Data Queues and the Distributed Program APIs in the same program. The Distributed Program API is certainly a welcome addition, but it does not render the existing techniques obsolete.

The Tester Program

The Tester program, as illustrated in Figure 1 and described in this article, includes the Visual Basic code for the form and a Visual Basic equivalent of the EHNDPW.H file, in which I provide function declares for the Distributed Program APIs.

This code is available on the Midrange Computing BBS in the AS/400 file download area, or directly from me. The BBS number is listed on page 2 of this issue of PCSE.

If you prefer, you can send your request for the code to me at the address shown below. You’ll need to include a self-addressed, stamped envelope with 55 cents postage for U.S. addresses (foreign subscribers, please determine the correct postage and prestamp your envelope with U.S. postage). You’ll also need to include one 3.5-inch

blank, IBM-formatted diskette. Requests without postage or the diskette will not be processed.


I especially want to thank Mike Young and his developers at the IBM Rochester lab. Mike called me about some other issues, and during our conversation, I mentioned that I was working with the Distributed Program APIs. At the time, I encountered what I thought might be a bug in the DLL. The problem was with the EHNDP_GetParm API. Mike confirmed the problem and sent an updated version of the DLL to me. He also indicated that this correction will be made available as a PTF at some point. The version of EHNDPW.DLL that I have is dated 6/27/95. The version distributed with SOA is 3/30/95. If you install the SOA code and have that version of the file, you will encounter the bug. I cannot provide the updated version of the DLL, so you will have to monitor either the IBM PTF list (SF97310), or check future issues of PCSE for notification of the public availability of the fix.

Finally, I want to thank Daniel Appleman of Desaware in San Jose, California. Daniel helped me with the code required to reference a parameter on the EHNDP_GetParm API. Daniel specializes in Visual Basic API programming. In addition to creating tools for Visual Basic, he wrote the definitive book on accessing Windows DLLs from Visual Basic. I’ve listed the book title below. If you’re going to work with Visual Basic and the Client Access/400 or PC Support APIs, you will find this book to be an outstanding resource.


Visual Basic Programmer’s Guide to the Windows API, Daniel Appleman, Ziff- Davis Press, 1993 (ISBN 1-56276-073-4).

Tester Diskette Address Craig Pelkie PO Box 1473 Valley Center, CA 92082-1473

The_Distributed_Program_APIs12-00.jpg 450x445

Figure 1: The Distributed Program API Tester Dialog

Purpose Start a conversation with an AS/400. If successful, a handle for the conversation is returned.


hWnd Handle to the window. lpszSystemName ASCIIZ string containing the system name, or NULL for default system. lpszAppName ASCIIZ string of unique application identifier. Can by NULL. lphSystem Handle to the conversation for the system.

Figure 2: The EHNDP_StartSys API

Purpose Get the name of the system used when starting the connection with


hWnd Handle to the window. hSystem Handle to the system. This is from the lphSystem parameter on EHNDP_StartSys. lpszSystemName 9-character buffer where the name of the system

will be written (8-character system name, 1 space for terminating NULL character).

Figure 3: The EHNDP_GetSysName API

Purpose Create a program object (handle to the program) for a given library and program name.


hWnd Handle to the window. lpszProgramName ASCIIZ string containing the name of the AS/400

program to be called. lpszLibraryName ASCIIZ string containing the name of the AS/400 library where the program is located.
lphProgram Handle to the program object.

Figure 4: The EHNDP_CreatePgm API

Purpose Add a parameter to the program identified by the program handle. Use this

API for each parameter to be passed. Parameters are added to the program in the order that this API is called.


hWnd Handle to the window. hProgram Handle to the program object (from EHNDP_CreatePgm). uiType The type of parameter. This can be EHNDP_INPUT, EHNDP_OUTPUT, or

EHNDP_INOUT (see EHNDPW.H for definitions of those constants). ulLength The length of the parameter.
lpParameter Pointer to the buffer where the parameter value is located for INPUT or

INOUT parameter types; or pointer to buffer where parameter value will be returned for OUTPUT or INOUT parameter types.

Figure 5: The EHNDP_AddParm API

Purpose Calls the program identified by the program handle. The return code indicates the success or failure of the call.


hWnd Handle to the window. hSystem Handle to the system from EHNDP_StartSys. hProgram Handle to the program object (from EHNDP_CreatePgm).

Figure 6: The EHNDP_CallPgm API

Purpose Retrieve the parameter identified by the index. You have to call this API for every parameter for which you want to retrieve a value.


hWnd Handle to the window. hProgram Handle to the program object (from EHNDP_CreatePgm). uiIndex Number of the parameter to retrieve. Parameter count starts at 0. lpuiType Pointer to the type of parameter (EHNDP_INPUT, EHNDP_OUTPUT,

EHNDP_INOUT). length The length of the parameter in bytes. lplpParameter Pointer to a pointer that indicates where the parameter value is written.

Figure 7: The EHNDP_GetParm API

Purpose Get the number of parameters for the program identified by the program handle.

hWnd Handle to the window.
hProgram Handle to the program object (from EHNDP_CreatePgm). lpusCount Unsigned integer containing the number of parameters.

Figure 8: The EHNDP_GetParmCount API

Purpose Delete the program object (construct in PC memory) identified by the handle.


hWnd Handle to the window. hProgram Handle to the program object (from EHNDP_CreatePgm).

Figure 9: The EHNDP_DeletePgm API

Purpose Stop a conversation with the system identified by the handle.


hWnd Handle to the window. hSystem Handle to the system that was created by the EHNDP_StartSys API.

Figure 10: The EHNDP_StopSys API

API Description

EHNDP_GetPgmName Get the name of the program used on the EHNDP_CreatePgm API. EHNDP_GetLibName Get the name of the library used on the EHNDP_CreatePgm API. EHNDP_SetParm Set the parameter value identified by the index. Use this to change a parameter value, after using the EHNDP_AddParm API. EHNDP_SetPgmName Set the name of the program.

EHNDP_SetLibName Set the name of the library. EHNDP_GetMsgCount Get the number of messages returned by the AS/400. EHNDP_GetMsgId Get the message ID of the message returned from the AS/400. EHNDP_GetMsgType Get the type of message returned from the AS/400. EHNDP_GetMsgLen Get the length of the message returned from the AS/400. EHNDP_GetMsgSev Get the message severity of the message returned from the AS/400. EHNDP_GetMsgFile Get the message file name and library for the message returned from the

AS/400. EHNDP_GetMsgText Get the message text returned from the AS/400. EHNDP_GetSubstTextLen Get the length of the substitution text for the message returned from the

AS/400. EHNDP_GetSubstText Get the substitution text for the message returned from the AS/400.

Figure 11: Other Distributed Program APIs



Support MC Press Online

$0.00 Raised:

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: