Uninformed: Informative Information for the Uninformed

Vol 1» 2005.May


Introduction

There is perhaps no issue more dear to a developer's heart than the issue of interoperability with third-party applications. In some cases, software that is being written by one developer has to be altered in order to make it function properly when used in conjunction with another application that is created by a third-party. For the sake of illustration, the lone developer will henceforth be referred to as the protagonist given his or her valiant efforts in their quest to obtain that which is almost always unattainable: interoperability. The third-parties, on the other hand, will be referred to as the antagonists due to their wretched attempts to prevent the protagonist from obtaining his or her goal of a utopian software environment. Now, granted, that's not to say that the protagonist can't also become the antagonist by continuing the ugly cycle of exposing compatibility issues to other would-be protagonists, but for the sake of discussion such a point is not relevant.

What is relevant, however, are the ways in which an antagonistic developer can write software that will force other developers to work around issues exposed by the software that the antagonist has written. There are far too many specific issues to list, but the majority of these issues can be generalized into one category that will serve as the focus for this document. To put it simply, many developers make assumptions about the state of the machine that their software will be executing on. For instance, some software will assume that they are the only piece of software performing a given task on a machine. In the event that another piece of software attempts to perform a similar task, such as may occur when two applications need to extend APIs by hooking them, the results may be unpredictable. Perhaps a more concrete example of where assumptions can lead to problems can be seen when developers assume that the behavior of undocumented or unexposed APIs will not change.

Before putting all of the blame on the antagonists, however, it is important to understand that it is, in most cases, necessary to make assumptions about the way in which undocumented code performs, such as when dealing with low-level software. This is especially true when dealing with closed-source APIs, such as those provided by Microsoft. To that point, Microsoft has made an effort to document the ways in which every exposed API routine can perform, thereby reducing the number of compatibility issues that a developer might experience if they were to assume that a given routine would always perform in the same manner. Furthermore, Microsoft is renowned for attempting to always provide backwards compatibility. If a Microsoft application performs one way in a given release, chances are that it will continue to perform in the same fashion in subsequent releases. Third-party vendors, on the other hand, tend to have a more egocentric view of the way in which their software should work. This leads most vendors to dodge responsibility by pointing the blame at the application that is attempting to perform a certain task rather than making their code to be more robust.

In the interest of helping to make code more robust, this document will provide two examples of widely used software that make assumptions about the way in which code will execute on a given machine. The assumptions these applications make are always safe under normal conditions. However, if a new application that performs a certain task or an undocumented change is thrown into the mix, the applications find themselves faltering in the most unenjoyable ways. The two applications that will be analyzed are listed below:

  1. McAfee VirusScan Consumer (8.0/9.0)
  2. ATI Radeon 9000 Driver Series

Each of the assumptions that these two software products make will be analyzed in-depth to describe why it is that they are poor assumptions to make, such as by describing or illustrating conditions where the assumptions are, or could be, false. From there, suggestions will be made on how these assumptions might be worked around or fixed to allow for a more stable product in general. In the end, the reader should have a clear understanding of the assumptions described in this document. If successful, the author hopes the topic will allow the reader to think critically about the various assumptions the reader might make when implementing software.