Using the IBM Developer API Extensions for OS/2 Warp
by Todd Crowe
In Volume 8 of The Developer Connection News, David E. Reich introduced you to the IBM Developer Application Programming Interface (API) Extensions for OS/2 Warp. Briefly, the Developer API Extensions are a set of approximately 750 APIs and 300 messages that provide substantially the same function as the corresponding Windows APIs and messages, with the same names.
To run OS/2 applications that use these APIs, install the Developer API Extensions (hereafter called Extensions) from The Developer Connection catalog in the "IBM OS/2" category on the DevCon for OS/2 CD-ROMs. To develop applications that use the Extensions, install the current Developer's Toolkit for OS/2 Warp from the "Developer Toolkits" category.
This article outlines steps for using the Extensions to port a Windows application to OS/2. Starting with a sample Windows application, I will guide you around potential pitfalls and explain how to overcome a few difficulties. The result: a mixed-mode Extensions/native Presentation Manager (PM) application!
- 1 Understanding the Interface
- 2 Not a Windows Emulator
- 3 Porting an Application
- 4 Mixing It Up With OS/2
- 5 A Finished Product
Understanding the Interface
For the moment, many more PC applications are written using APIs for Windows than those for OS/2. Recognizing this, we designed the Extensions to exploit existing Windows application source code while at the same time promote the authoring of OS/2 native code. Our approach was to do two things:
- Develop an OS/2 API set (the Extensions) that provides many functions similar to the Windows 32-bit API set.
- Promote IBM's own superior extensions over those of our competitors. (For example, promote OpenDoc for OS/2 over OLE, LAN Server over LAN Manager, OS/2's multimedia capabilities over Windows' capabilities, and so on).
Not a Windows Emulator
The Extensions are not a Windows emulator. They are extensions to OS/2's native API set. The Extensions are an interface layer that exists in various proportions inside, alongside, and on top of the OS/2 base and Presentation Manager.
The Extensions include support for many of the basic 32-bit Windows APIs, including memory management, threads, processes, semaphores, files, registry, window management, DDEML, graphics, metafiles, help, and printing. Some functions in these areas are currently not supported, such as memory mapped files, enhanced metafiles, and structured exception handling. In addition, some functions are not fully compatible with the corresponding Windows function; important differences are discussed later in this article.
Because the Extensions are extensions to OS/2, any application developed with the Extensions is really an OS/2 application. Therefore, it should look and feel like a native OS/2 application. Most of these differences are apparent only in the look and feel of the application and do not require code changes (for example, controls and online help look and feel like those in a native OS/2 application). Finally, as implied above, the Extensions do not include any support for Windows extensions such as security, networking, OLE, or multimedia.
Porting an Application
So how easy is it to port a Win32 application to OS/2 with the Extensions? If your application uses only, or mostly, the APIs and messages supported by the Extensions, the answer is, "Very easy." The accompanying Windows application (SAMPLE) demonstrates all of the steps necessary. SAMPLE contains all of the basic features a Windows application is likely to include. (You can find it on the DevCon for OS/2 CD-ROM, in the category "Source Code from The Developer Connection News", or you can view the files directly on disc 1 in the directory \source\devnews\vol10\dapiesrc).
There are essentially eight steps to follow to port an application to OS/2. The steps provided here apply specifically to SAMPLE, but you can apply them in general when you port your own Windows application:
- Convert the Windows 32-bit source help files SAMPLE.RTF and SAMPLE.HPJ to an OS/2 .IPF file (or, alternatively, directly to an .HLP file) using SMARTHLP.EXE, a component of the Source Migration Analysis Reporting Toolset (SMART) from One Up Corporation. (SMART is available on your DevCon for OS/2 CD-ROMs in the "Development Tools" category.)
- Convert the Windows 32-bit source resource file SAMPLE.RC to an OS/2 resource file using SMARTRC.EXE, another component of SMART.
- Move the lines in SAMPLE.HHH (generated in step 2) to SAMPLE.H.
- Change the line in SAMPLE.C from #include <windows.h> to #include <os2win.h>.
- Change the code in SAMPLE.C that uses string resource IDs to use the MAKEINTRESOURCE() macro with the numeric IDs that SMARTRC.EXE generated in SAMPLE.HHH.
- Create a .DEF file for the executable SAMPLE.EXE; the minimum recommended stack size is 64KB.
- Create a new makefile for the project.
- Manually port the Windows APIs not directly supported by the Developer API Extensions and add code for the desired OS/2 extensions (for example Workplace Shell enablement). The ported SAMPLE application adds a container window to the application.
As you can see, the first seven steps are simple and could even be automated if desired. Step 8 is the only one that might require a relatively large amount of new code. Not coincidentally, however, step 8 is also when you would want to enhance the OS/2 version of your application beyond the original Windows application. In other words, much of the work required in step 8 would be expected by a customer in any case.
Before discussing step 8, which is the focus of the last part of this article, there are a few caveats and suggestions that should be mentioned concerning the first steps:
- Step 1: The SMARTHLP.EXE program will not convert 100% of most help files; the automatic conversion will do much of the required work for you, but you will need to spend time reformatting and rewriting parts that use advanced or unsupported features. This shortcoming results from the considerable differences between Windows' and OS/2's online help facilities. Because an Extension application is supposed to look like a regular OS/2 application, the application should have help that looks like regular OS/2 help--even if it requires additional work for the developer. You can also use IBM's Hyperwise Version 2.0 to import your Windows' help files, reformat sections and edit. A lite version is available on the DevCon for OS/2 CD-ROM.
- Step 2: The Extensions do not currently support the binary formats used by Windows resources. As a consequence, in addition to requiring that resource files be converted, a small number of the APIs are not fully compatible with their Windows counterparts and might require special attention. Some important differences are described later in this article.
- Steps 3 and 5: Developer API Extensions Release 1.0 includes support for string resource IDs; these steps are optional.
- Step 4: Another option is to write your own version of WINDOWS.H tha tincludes OS2WIN.H.
Mixing It Up With OS/2
Because the Extensions are extensions to OS/2 and not an emulation environment, the ability to interoperate with the rest of OS/2's API set is important. Most developers will want to make OS/2 native API calls in their applications that use the Extensions. In fact, it is recomended that all developers who use the Extensions will take advantage of native OS/2 functions.
The ported version of SAMPLE is a mixed-mode application. It contains all of the functions of the original Windows application, plus it uses a container for the client window. The source for the container (CONTAIN.C) is basically the same as the OS/2 Warp Toolkit container sample code with a few modifications.
The Extensions version of SAMPLE demonstrates several important issues that you are likely to encounter if you try to make your Extension application interoperate with native OS/2 APIs.
Mixing Source Code
The first issue is how to mix the source code. The Extensions and OS/2 native APIs share the same name space; that is, many flags, structure names, and messages have the same names. Unfortunately, they also usually have different binary values or formats. For example, the CreateDialogIndirect API takes a pointer to an OS/2 DLGTEMPLATE structure, not a Windows DLGTEMPLATE structure. There are two solutions to this problem:
- You can keep each type of code in separate source files (as is done in SAMPLE), or
- You can build your own header files in which you have somehow altered the symbol names.
How to Handle Frame and Client Windows
Second, in Windows there is no distinction between the frame and client windows. Whereas PM usually creates a frame and a client window for each top-level window, Windows creates one window that has a client area and a non-client area. This is an important difference. Because an Extension application is really a PM application, each top-level Extension window has a frame window and a client window. This fact is transparent to the Extensions but must be considered when interoperating with PM APIs.
In SAMPLE, this difference is accounted for in the CreateContainer function. CreateContainer is called in the Extension source with a window handle returned from CreateWindowEx. This window is an overlapped window and, therefore, the window handle returned is actually a PM frame window handle. The handle of the client window for this frame is never made available to the Extensions--either via API calls or in message parameters. You should not try to use a client window handle obtained from a PM API in an Extension or message, nor should you try to destroy or replace the client window created by the Extensions. The container is supposed to be the client window in SAMPLE, but since we cannot destroy or supplant the default client window, we must create the container as a child of the client window. CreateContainer does this after first querying the client window handle using the parent frame window handle.
How to Handle Message Interoperability
Interoperability of messages is the third point that the SAMPLE program illustrates. In general, if a window is created using an Extension, the window procedure for that window will receive Extension messages; similarly, if a window is created using a PM API, the window procedure will receive PM messages. The SAMPLE application demonstrates that the same property applies to subclassing as well. A PM subclass procedure is used to intercept messages destined for the client window. The subclass receives PM messages even though the client window is part of an Extension window.
Differences in Window Positioning
The handling of the WM_SIZE message in the PM subclass broaches the fourth issue. The device coordinate system used by Windows is inverted with respect to PM, that is, the origin (0,0) is in the upper left (rather than the lower left) corner of the window or screen. Because the container is a child of an Extensions window, the Extensions will attempt to keep it aligned to the upper-left corner of its parent. Thus, the call to WinSetWindowPos must not only change the size of the container, but the call must also reposition the window to the origin.
Differences that Prevent Full Interoperability
The final issue, which cannot be demonstrated by a working application, is that the Extensions are not fully interoperable. Window handles are the only data structures that can readily be used in both Extensions and PM APIs.
Device context and presentation space handles should be considered to be incompatible, even though they are not completely so. Internally they are essentially the same data structure, but because of the inverted coordinate spaces and other differences between the two, Extensions graphics calls should be restricted to using device context handles from the Extensions and Graphics Programming Interface (GPI) calls to presentation space handles from PM APIs.
Base OS/2 handles (for example, file and semaphore handles) are completely incompatible and cannot be interchanged. This last incompatibility with Windows handles is partly due to the fact that Windows NT uses a unified handle manager for all of its base handles and OS/2 does not, and partly because most of the base objects have significant semantic and functional differences between the Windows NT versions and their OS/2 counterparts.
A Finished Product
One more thing should be mentioned: the Extensions are not a porting tool; they are an extension to OS/2. As such, the Extensions let you create and maintain application source code that can be compiled for either Windows or OS/2. Finally, the ability to interoperate between the Extensions and native OS/2 APIs allows you to release enhanced OS/2 versions of your applications, even if you have only a limited amount of OS/2 development experience.
Note: When porting your Windows application, remember to abide by all applicable license agreements. For more information about the Extensions, refer to the OS/2 Warp Developer API Extensions Guide available on your DevCon for OS/2 CD-ROMs.