Nancy Winnick Cluts
Microsoft Corporation
November 1998
Summary: Details the cross-platform development of Microsoft® Internet Explorer 4.0 for UNIX using the Microsoft Win32® API. (4 printed pages)
Yes, you read that correctly. I said that you can create a UNIX application using the Win32 application programming interface (API). And I have proof. Internet Explorer 4.0 for UNIX was written using the Win32 API. I bet you'd like to know how the team pulled that one off. (I know I did!) If you are interested in the details, read on.
At TechEd in New Orleans, LA, in June 1998, Digvijay Chauhan, Development Manager of the Internet Explorer UNIX team, outlined the cross-platform issues in Internet Explorer 4.0 (for a full list of cross-platform issues, search for my article "Internet Explorer Runs Cross-Platform" on the MSDN Online Web Workshop site at http://msdn.microsoft.com/workshop/) as well as how to use the Win32 API for cross-platform development. This article is based on the second part of his presentation: Win32 development on Unix. Another session, titled "Targeting Unix & Windows Platforms with a Single Code Base: A Case Study" (IOP05) was given at the Professional Developers Conference in Denver.
Imagine that you are on a development team and you are told that you need to develop a browser using the Win32 API and deliver it on both the Win32 and Unix (Solaris) platforms. In order to do this, you need to take into consideration the user interface differences as well as how you are going to actually code the application. X-Windows has a different user interface than Windows. With the pace of the software industry, you do not have the luxury of spending a lot of time and resources on this project—you must get this browser to market rapidly. You also must be sure the Unix version has the same rendering fidelity as the Win32 version. Finally, you must incorporate the Unix look. That's the challenge that the Internet Explorer UNIX team faced and met.
The targeted time frame was 2–3 months after the Win32 version shipped. The team consisted of approximately 50 people. There were about 600 Win32 functions that were used by Internet Explorer. There wasn't time to start from scratch and create their own Win32 layer for Unix, so they looked at vendors that already had such a layer, and tools available. They found two such vendors: Bristol and Mainsoft. Throughout this project, there were some issues the team had to solve, including differences in focus, the Component Object Model (COM), the registry, performance, fonts, UI issues, and portability.
The biggest area of trouble (read: bugs) had to do with focus. On X-Windows, the user can configure the workstation for multiple Window Manager modes and each Window Manager supports multiple modes. This leads to some interesting differences in the use of focus on Unix versus Win32. On a Win32-based platform, when the user clicks the mouse once on a window, that window gains the focus. On X-Windows, you can configure your system such that the focus follows the mouse. That is, when you move the mouse to a window, the focus automatically moves to that window. The workstation can also be set up to support auto raise focus—when the window gets the focus it is automatically put in the foreground. X-Windows also supports the single-click to focus scheme that Win32 supports. The Internet Explorer Unix team had to make sure the browser they created also supported these different forms of focus.
In Microsoft Windows®, it is common for developers to create modal windows. A modal window is a window that, when it has the focus, does not let any other window within the application get the focus until the window is dismissed. For example, if you click the View menu on Internet Explorer and choose Internet Options, you will bring up a window that stays in focus until it is dismissed—if you click the Internet Explorer main window, you will hear a ding and the window will not come into the foreground. Windows developers create modal windows through the use of the GetMessage, TranslateMessage, and DispatchMessage functions in a loop. X-Windows employs a Window Manager that must be told, via hints, whether a window is modal or not. Unfortunately, this information is only read once, when the window is shown. The solution to this difference was to use a new window style hint to tell the Window Manager the window modality prior to the window being shown.
Internet Explorer relies heavily on the Component Object Model (COM) in order to function. In fact, any of the window items you see that are outside of the client area of the screen (for example, the rebar, the dialog boxes, and so on) are all COM objects. They use COM to communicate between the browser and the other COM objects. One important portability problem faced by the team involved using C code to access COM object methods directly via virtual table (known as a vtable) structure pointers. The vtable layout is compiler-specific. As a result, the layout of the pointers is different on Solaris. The solution was to replace the C code accessing COM objects with C++ code.
On Windows, the registry is used to store and access information such as user preferences. Most Windows applications read these values from the registry in order to persist data from session to session. In Unix, a user can log on to his workstation and use his home directory from any machine with all of his settings preserved. Because the registry resides on only one machine, this is problematic. The team had to figure out how to share registry information across machines.
Another registry-related issue is synchronization of registry settings across processes. Okay, that's a complex sentence. In real terms: Microsoft Internet Explorer and Microsoft Outlook® Express share registry settings. If you change a registry setting in Internet Explorer, Outlook Express immediately reflects the changes.
The solution was to keep the registry in a location that is shared by all workstations, leveraging a single home directory. This way, different processes, regardless of machine, can be in synch.
The Internet Explorer Unix team created some simple and effective in-house performance tools to analyze performance bottlenecks and solve them. One tool wrapped all of the Win32 APIs in order to log the calls to the APIs as well as determine which thread called the API. This information was used to identify frequently used APIs and determine which should be optimized (the ones that were used often) and which were taking the most time.
Another tool was created to analyze heap space. This was done by mapping the memory allocation functions (malloc, realloc, and so on) along with thread identifiers. They were then able to identify resource hogs (image copy was a big one) and where they could group allocations in order to maximize performance.
In order to help in the debugging process, they created a program that modified exception-handling code to determine (via a stack trace) what caused Internet Explorer to crash. This was particularly helpful in determining if the testers had found a new bug or one that already existed, albeit in a new user scenario.
The final tool that was created was a quick and dirty profiler. This profiler would suspend all threads in a process, sample the program counter, and map the symbols to get a running count of where the application was spending most of its time. Here again, the team could go back and optimize that code.
There are a few exceptions to font support using Internet Explorer 4.0 on UNIX. Some fonts are simply not available on Unix. In general, Windows fonts will be mapped to those available on a particular Unix server. The Verdana, Arial, and Sans Serif fonts are mapped to the Helvetica font. The Marlett font is not supported on UNIX at all. Internet Explorer 4.0 Unix maps fonts to an equal or smaller point size. In addition, X-based servers can have different configurations and different font installations. As a result, it was necessary to map fonts for specific font installations on the server. Internet Explorer 4.x shipped some prebuilt font caches for standard server configurations. For nonstandard configurations, a font cache is built the first time the browser starts; however, this proved to cause a slowdown in startup. As a result, Internet Explorer 5.0 has changed to an alternate design.
The Windows interface is different from the look you get when you run X-Windows–based Motif or common desktop environment (CDE) applications. The Internet Explorer Unix team had to take into consideration the different appearance for their version of the browser. Some of the interface issues that the team had to address were:
When it got down to coding, there were some interesting issues that the team had to solve, including:
All of this was a lot of work and the Internet Explorer Unix team learned a lot from it. In the future, they plan to use a common code base between their Win32 and Unix versions so that a change in one will automatically be reflected in the other. They are planning to use the Apoge compiler (http://www.apogee.com/) for this common code base. They also plan to incorporate the feedback they get on interface issues. In the meantime, you now know that you, too, can develop your Unix application on Win32. The Internet Explorer team did it and so can you.