Windows API 的批判(略译)

 http://www.spinellis.gr/pubs/jrnl/1997-CSI-WinApi/html/win.html
This is an HTML rendering of a working paper draft that led to a publication. The publication should always be cited in preference to this draft using the following reference:

    * Diomidis Spinellis. A critique of the Windows application programming interface. Computer Standards & Interfaces, 20(1):1-8, November 1998. (doi:10.1016/S0920-5489(98)00012-9)

This material is presented to ensure timely dissemination of scholarly and technical work. Copyright and all rights therein are retained by authors or by other copyright holders. All persons copying this information are expected to adhere to the terms and constraints invoked by each author's copyright. In most cases, these works may not be reposted without the explicit permission of the copyright holder.

A Critique of the Windows Application Programming Interface
Windows API 的批判

Diomidis Spinellis
University of the Aegean
83200 Karlovasi
Greece
email: dspin@aegean.gr
December 1997
原文: http://www.spinellis.gr/pubs/jrnl/1997-CSI-WinApi/html/win.html
刘建文略译( http://blog.csdn.net/keminlau

Abstract:

The architecture, interface, and functionality of the Windows Application Programming Interface (API) make it difficult to master and use effectively, and contribute negatively to the safety, robustness, and portability of the applications developed under it. The API is structured around a large and constantly evolving set of functions and is based on a problematic shared library implementation. The provided interfaces are complicated, non-orthogonal, abuse the type system, cause name-space pollution, and use inconsistent naming conventions. In addition, the functionality of the interface suffers from inconsistency, incompleteness, and inadequate documentation. Application developers, programming tool vendors, and Microsoft should face the above problems and provide appropriate solutions.
当前(1997)的Windows API的架构、接口和功能很难被掌握和使用,并且还对基于它的应用程序的安全性、健壮性和灵活产生负面的影响。主要原因,设计这些API的应用需求在不断扩大和变化之中;API所基于的共享库的实现也很多是有问题的。如接口复杂、非正交性、滥用类型系统、污染名字空间和使用不一致的命名约定。还有,文档的不一致、不全面和不友好损害了API的使用。。
Keywords: Microsoft Windows; Application Programming Interface; Win32

Introduction

Microsoft Windows 95 and Windows NT (from now on referred-to as ``Windows'') are increasingly becoming widely adopted as operating system platforms for desktop applications, back-office servers, and research [1]. Their programming interface, currently distributed and documented as the ``Microsoft Platform Software Development Kit'' [2] (SDK), provides a set of functions, data types, structures, macros, and tools for writing user and system software to run under Windows. Although application writers can be isolated from the SDK by using libraries, scripting, visual and fourth-generation languages, or utilising programmable components, ultimately the SDK provides the operating system interface thus affecting the robustness, portability, performance, safety, and ease of Windows programming.
Windows的普及已经深入到桌面应用、办公室服务应用。Windows API(被分发名为平台SDK)提供了各种函数、数据类型、结构、宏和其它工具给用户开发Windows应用。虽然用户可以撇开SDK,转而使用各种代码库、脚本、第四代可视化语言或者其它可编程组件开发应用,但最终还是由SDK来提供操作系统的接口,并控制了应用的健壮性、灵活性、功能、安全性。

The first versions of Windows provided a graphical environment to the MS-DOS operating system. The current versions of Windows provide a 32-bit graphical, multi-tasking, networked operating system [3] used by thousands of workstation and server applications. The core SDK Application Programming Interface (API) covers an extremely broad area providing the interfaces listed bellow.
Input and output devices:
    mouse, keyboard, pen, screen, printer, and sound.
User interface elements:
    windows, menus, dialogs, input widgets, the clipboard, and internationalisation functions.
System services:
    files, memory, hardware, system databases, and networking.
Graphical elements:
    bitmaps, fonts, drawing primitives, area management functions), and 3D graphics rendering.
SDK的核心API横盖了非常广泛的功能和接口,如下:
  • 输入输出设备:鼠标、键盘、输入笔、显示器、打印机和声卡;
  • 用户界面元素:窗口、菜单、对话框、剪贴板、国际化函数;
  • 系统服务:文件、内存、硬件(驱动)、系统数据库(注册表)、网络服务;
  • 图形元素:位图、字体、绘图原语、面积管理函数和三维图形渲染。

An additional number of APIs are provided and documented as part of the Windows Platform SDK. The use of some of them is required in order to develop an application that will satisfy the licensing requirements of Microsoft's ``Designed for Windows NT and Windows 95'' Logo Program. These APIs cover the following areas:
    * the Microsoft's Component Object Model (COM), Object Linking and Embedding (OLE), application automation, and ActiveX,
    * shell interfacing,
    * telephony interfaces (TAPI),
    * remote access services and procedure calls (RPC),
    * Internet networking, W3 server interfacing (Winsock, ISAPI),
    * messaging (MAPI), and
    * game applications (DirectX 2).
还有一些额外的API被划进平台SDK。这些API是为了支撑“Designed for Windows NT and Windows 95'”的LOGO招牌的。
  • COM、OLE、应用自动化、ActiveX
  • shell接口
  • 电话通信接口(TAPI)
  • 远程访问服务和过程调用(RPC)
  • 互联网连接、W3服务接口(Winsock,ISAPI)
  • 消息传送(MAPI)和
  • 游戏应用(DirectX 2)

The Windows platform SDK also documents a number of interfaces for entities that are not yet part of the standard Windows distributions such as the Microsoft SQL, Transaction, and Exchange servers, the management console and clustering interfaces, the Win32 Internet functions, and the Open Database Connectivity Interface (ODBC). Although many of the shortcomings of the basic Windows API are also evident in the above mentioned interfaces, we will not cover these in this article.
另外还有一些不被装进标准Windows分发包的的API。如Microsoft SQL、事务(Transaction)和 Exchange servers, 管理控制台、WIN32互联网功能和ODBC。虽然Windows API在这些接口上有很多明显的缺点,但是我们不打算在这里讨论它们。

The Windows interface is specified using C language bindings, although due to the nature of its implementation -- as a set of shared libraries callable using the calling convention commonly associated with Pascal programs -- many of its functions are accessible from other languages and programming environments.
In this article we will critically examine the architecture, interface, and functionality of the Windows API and point to a number of problems associated with it. We will argue that because of these problems the Windows interface:

    * is difficult to master and use effectively,
    * can be used to distort competition in the marketplace,
    * contributes negatively to the safety, robustness, and portability of the applications developed under it.
Windows API被指定使用C语言绑定使用的,但是出于它的实现的实际(它的共享库可以被遵循Pascal 调用约定的程序调用),它的大部分函数可以被其它语言和编程环境调用。
本文重点拷问Windows API 的架构、接口和功能,指出它所存在的问题。这些接口设计使:
  • 接口本身难以掌握和有效使用
  • 扰乱市场竞争
  • 对应用的健壮性、灵活性、功能、安全性产生负面效果

The remainder of this article is structured as follows: in the next section we examine the API's structure, size, and implementation looking on how these affect software development, reliability, and marketplace competition. In section 3 we examine the interface provided by the Windows API and identify problems related to the complexity and non-orthogonality of the provided interfaces, the type system, name-space pollution, inconsistent naming conventions, and portability. In section 4 we look beyond the interface into the actual functionality provided by the API and provide examples of inconsistency, inadequate documentation, and incompleteness. Finally, the last section contains proposals on how application developers, programming tool vendors, and Microsoft should handle the identified API problems.
本文余下部分内容如下:
下一节,我们讨论API的结构、规模和具体实现,看看它们如何影响软件的开发,软件的可靠性和市场竞争。
第三节,我们讨论API的不良设计所产生问题的各个方面,如接口复杂、非垂直、类型系统、名字空间污染、不一致的命名约定和灵活性。
第四节,我们深入接口内部,看看API实际功能的实现,用实例说明它的不一致性、文档的不友好性和不完全性。
最后,我们给出建议,指出应用开发者、编程工具生产商和MS如何面对这些问题。

Size, Structure, and Implementation
规模、结构和实现

  The Windows API is accessed through a very large and complicated set of elements. Its size is difficult to judge because what exactly constitutes it is far from clear. The Windows SDK definition and its contents change rapidly according to Microsoft's strategic and marketing interests. As an example the October 1996 edition of the Microsoft Development Library documents the Internet Server API (ISAPI) as part of the Win32 Software Development Kit (SDK), but documents other server related APIs (such as the Open Database Connectivity -- ODBC -- API) as separate entities. The April 1997 version of the Microsoft Development Library documents all Windows interfaces under the roof of a single ``Platform SDK''.
In this article we will consider the Windows API (Win32) to consist of the items supplied as parts of Microsoft's Win32 Software Development Kit. The POSIX subsystem of Windows NT, although part of the Win32 SDK, is separately installed and documented; for this reason we will not consider it as part of Win32.
Windows API 包含相当多和复杂的内容,从而很说明清楚它具体由什么组成,所以也很难对它作出很详细的评论。Windows API多而杂的原因是MS的策略和市场兴趣的变动。
本文将考虑讨论包括在Win32 SDK中Windows API条目。虽然Windows NT的POSIX 子系统也是Win32 SDK的一部分,但是它是独立的安装和说明的,所我们不认为它是Win32 的一部分。

A file (WIN32API.CSV) supplied together with the Win32 SDK lists 9067 API elements (functions, interface methods, structures, messages, macros, properties, etc.) This number although large does not include about 29000 constant definitions (constants defined using the #define mechanism of the C preprocessor) and about 4800 type definitions (C typedefs) that can be found by going through all C header files that are part of the SDK, nor does it include the Unicode, ASCII, and character set neutral function forms. A summary of some key metric sizes of the Win32 API is provided in Table 1.
Win32 SDK 里面的一个叫WIN32API.CSV的文件列出了9067个API 元素(函数、接口方法、结构、消息、宏、属性等)。这个数目虽然大,但还没有包括将近29000个常量定义(使用C预处理指令#define 定义的常量)和约4800个(通过C头文件可找到的)类型定义(C typedefs)和Unicode, ASCII等字符集相关数据。看下表:


Element Number
Number of root header files 129
Number of import libraries 48
Total number of header files 232
Header file size (Mb) 5.2
Header file lines (non empty non comment) 120516
Macro and constant definitions 33174
Type definitions 4858
Functions 3433
Interface methods 1462
Messages 858
Notification messages 180
Structures 1077
Properties 498
Enumeration types 110
Function error codes 1137
Table:  Win32 API key metrics


The large size and monolithic nature of the Win32 API negatively affect a number of areas related to software development. The huge number elements comprising the API make it difficult to master it and use it effectively. As a result the productivity of application architects, software developers, and maintainers is negatively affected.
In addition, the creation of systems providing the same services on different platforms is difficult, and, given the rapidly evolving nature of the API, could well be impossible. In the past, major advances in research and development of new hardware and operating system architectures such as the RISC processors and microkernels were leveraged on the ability to provide a Unix-like environment on top of the new architecture. With the domination of the Windows API new hardware and software architectures, in order to be accepted, will need to support the Windows API. Microsoft's exclusive control of the API can distort competition and market diversity.
Win32 API的大块头尺寸本质限制了它的软件开发领域。API的元素数量之巨也影响它被掌握和使用。最终的后果是严重影响程序员、软件架构师和维护人员的工作效率。
此外,把同一软件系统在不同平台移植也应变得相当困难,而API的快速演化特性更使平台移植不可能实现。在过去,开发和研究新硬件(像RISC处理器)和新操作系统架构(像微内核)的主要优点在于能够使用一个统一的仿UNIX环境来开发新架构。但市场被Windows API占领后,新硬件和新架构如果要被接受必须支持Windows API。这样Microsoft对API的独立控制会影响市场竞争。

Finally, given the size of the API, any formal proof of specific properties or the correctness of programs using it is an extremely difficult task. As a result, either the reliability of life-critical software will suffer, or such software will be developed, maintained, and operated in an environment isolated from the rest of the mainstream software. This will have important cost and interoperability consequences.
最后,由于API的规模,特定属性的形式证明和使用这些属性的程序的正确性的验证变得相当困难。因此,不管生命攸关的程序的可靠性得不到保证,这些程序的开发、维护和操作的环境都会被主流软件所孤立。这将具有严重成本和互操作性方面的后果。

Apart from its large size, one other problem related to the API structure is its reliance on a shared library system, the Windows Dynamic Linked Libraries (DLLs). The current implementation of the API and its binding mechanism provide no version and interfacing control over the applications that use DLLs and the libraries they are linked to. Although DLLs can be associated with a version number, at a given time only a single version of a DLL can be loaded on the system. As a result major library interface changes, such as the transition to 32 bit code, rely on a haphazard mixture of simple renaming and replacing of library modules for satisfying the new linkage requirements. One exemplar标本 result of this simple-minded approach is that application installation disks created with the Visual Basic 3.0 development environment on a Windows 95 platform will destroy the setup of a Windows 3.1 platform when an installation is attempted. In other cases where compatibility with older software had to be preserved, as was the case with the introduction of the Jet 2.0 database engine, a complicated set of new library modules and stubs had to be correctly installed for the system to function.
除了规模太大外,API还有另外一个问题,就是它对共享库系统--DLL的依赖。目前的API实现和绑定机制没有为使用DLL的的应用程序和这些DLL库本身提供版本和接口控制。虽然DLL可以分配一个版本号,但是系统一次只能载入一个单一版本的DLL。因此,当库接口更改了后,像从16位转为32位,为了满足新的链接需要必须混合改名和替换库模块来适应接口更改。这种弱智的适应方法的一个例子就是,把 Windows 3.1的应用移植到 Windows 95 时, Windows 3.1的应用的安装程序完全被废弃。另一个情况是要保持对老版本软件的支持。如Jet 2.0 被引进时,系统必须正确安装一大堆新库模块才能正常工作。
In addition to the above, the monolithic structure and large size of the API contribute to name-space pollution problems that it creates. Any non-trivial Windows application will need to include the windows.h header file which in turn includes more than 60 other header files comprising more than 70000 lines of C declarations and macro definitions.
除了以上几点外,大块头的API也污染用它开发的代码的名字空间。任何实用点的Windows应用都要把头文件windows.h 包进代码。这是个由超过60个其它头文件组成,合共7万多行C声明和宏定义语句。

Interface
接口

  The provided functions have a complex and non-intuitive interface with a number of mode changing flags and exceptions that unnecessarily complicate system application development. Space restrictions do not allow us to provide a detailed example; interested readers are encouriaged to discover for their own edification启发 the three different ways in which a read-only mode can be specified using the seven parameters of the CreateFile function.
API提供的函数都很复杂和不直观,每一个接口都有很多模式更改标志和异常标志,这样会增加开发不必要的复杂性。篇幅关系不允许我们提供更详细的例子,建议有兴趣的读者可以从CreateFile 函数使用七个参数的三种不同方法来指定文件的只读模式中得到启发。

Despite the apparent generality of functions such as CreateFile it would be a mistake to think that the Windows API provides a small set of generalised functions that cover a lot of ground by being combined in an orthogonal垂直 fashion. Win32 provides 91 functions that create entities (from CreateAcceleratorTable to CreateWindowStation). All those functions receive parameters of different types in wildly differing order; even similar functions that provide enhanced functionality (such as CopyFileEx) have the new arguments interspersed with the existing ones. The return value of the functions that create entities is also inconsistent. The following are representative examples of return value inconsistencies across functions that create different entities:
尽管CreateFile 表现出函数的一般性,但会给一个种错觉,以为Windows API提供少量的基本通用函数,再通过正交方式派生其它函数。Win32 提供了91个创建对象的函数(从CreateAcceleratorTable 到 CreateWindowStation)。这些函数都使用不同类型和顺序的参数。即使是相似的函数,像一些功能优化版本的函数(像CopyFileEx)也会和原函数有不同的参数。创建对象的函数的返回值也不一致。以下是一些创建不同对象返回值的不一致的例子:
CreatePipe
    returns TRUE for success and FALSE on error.
CreateFile
    returns a handle to the file object on success and the INVALID_HANDLE_VALUE constant on error.
CreateFileMapping
    returns a handle to the mapping object on success and NULL on error.
CreateTapePartition
    returns NO_ERROR on success and one of 15 constants (ERROR_BEGINNING_OF_MEDIA to ERROR_WRITE_PROTECT) on error.
CreateHalftonePalette
    returns a handle to the palette object on success and zero on error.

The complexity of the API increases even more with the provision of 131 ``extended'' functions (ending in Ex) that perform similar tasks to the original ones, but provide extended or sometimes just different functionality. For example, the CreateWindowEx function provides an additional parameter for specifying 21 ``extended'' window styles in addition to the 139 styles (27 basic and 112 class-dependent) allowed by the CreateWindow function, while WriteFileEx provides the functionality of WriteFile, but is designed solely for asynchronous operation. In addition to the above, 1226 functions exist in three flavours according to the character set they support: Unicode, ANSI (an 8-bit superset of the ASCII character set), and character set neutral. The Unicode and ANSI versions of the functions are named by appending the letter ``U'', or ``A'' respectively after the function name. The character set neutral functions are defined as a C preprocessor macro that calls one of the other two functions depending on the source code compilation specifications.
API的复杂性也以各种方式被增加着。像API提供了131个与原函数完成相似任务的预备“扩展”函数(以Ex结尾的)。比如,CreateWindowEx比CreateWindow多使用一个参数来指定21个扩展窗口风格;WriteFileEx 除了提供与WriteFile一样的功能外还提供异步处理方式。此外,还有1226个函数根据它们使用的字符集(Unicode, ANSI和character set neutral)的不同有多种变种。这些函数的Unicode和ANSI的版本分别用字母 ``U''和``A'' 区分;中立字符版本(character set neutral )则被定义为C预处理宏,按需求编译成相就的函数版本。

Type System Problems
类型系统问题

Although the current specification of ANSI C provides a type system that can be used to detect many type errors at compile time, the Windows API specification provides ample opportunities to break it by specifying in a large number of cases arguments with minimal type information associated with them.
Older releases of Windows declared the various ``handles'' (small integer constants used for identifying operating system entities) in a way that made them type compatible. Thus it was possible to pass to an API function that expected a window handle, a handle to a device context or a handle to a brush. The situation has improved with later releases of the Windows API which can (with the definition of the C preprocessor's ``STRICT'' symbol) perform type checking across different types of entity handles.
虽然目前的C语言规范提供的类型系统可以在编译时检测出很多类型错误,但是Windows API的规范提供了大量的机会逃过这种类型检测,如规定了大量的可选参数,这些参数拥有很少的类型信息。
Windows 老发行版本声明了各种不同的“句柄”(用以标识操作系统对象的整型常量),目的是为了类型兼容,为了可以把窗口句柄、设备上下文句柄和笔刷的句柄传给API函数。这种处理方式在Windows API 新发行版本中得到改进,新版本可以(通过C预处理的“STRICT”符号定义')对对象句柄的不同类型施行检测。
Other type-related problems persist. More than 150 functions pass an argument of type LPVOID or PVOID) which is a pointer to any type, in effect short-circuiting the compiler's type checking system. Some of the functions (e.g. CopyMemory) use this argument type legitimately for providing an interface to unstructured memory. Other functions however, typically pass a pointer of an appropriate type depending on the value of another argument. As an example the GetTokenInformation function which is used to retrieve a specified type of information about an access token can pass as an argument a pointer to ten different structures (TOKEN_USER to TOKEN_STATISTICS depending on the class of the requested token information which is also specified as an argument.
其它类型相关的问题依然存在。超过150个函数使用不定类型的指针(LPVOID 或 PVOID )作参数,这种类型的使用轻易的逃脱了编译器的类型检测。一些函数(如CopyMemory)为了访问无结构内存数据很合法地使用上了这种不定类型的指针作参数。但是,其它函数一般要传递特定类型的指针。比如像GetTokenInformation函数(功能是获取某一个访问标号所属类型的特定信息)就
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值