`
buliedian
  • 浏览: 1238597 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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等字符集相关数据。看下表:


Table:Win32 API key metrics
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


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函数(功能是获取某一个访问标号所属类型的特定信息)就
分享到:
评论

相关推荐

    《康德三大批判新译》简介.docx

    《康德三大批判新译》简介.docx

    逻辑与批判性思维训练资料.zip

    0.8元必做答案作业2 逻辑与批判性思维训练pdf 1必做逻辑与批判性思维训练作业题.pdf 2必做作业答案逻辑 与批判性思维训练作业题pdf 2元参考普通逻辑学综合练习题及其答案pdf 3参考普通逻辑学综合复习资料.pdf ...

    超越感觉:批判性思考指南

    美国纽约州立大学德里校区荣誉退休教授,是国际公认的...其代表作还有:《思维的艺术》(1984)、《成为批判的思考者》(1989)、《批判地思考伦理问题》(2007)等等,他的许多书都出了多个版本,深受学生和广大读者的欢迎

    哥达纲领批判-原文[汇编].pdf

    "哥达纲领批判-原文[汇编].pdf" 这篇文件是一份马克思和恩格斯对哥达纲领的批判,写于1875年,是一种政治文献。下面是从这篇文件中提炼出来的知识点: 1. 哥达纲领是什么?哥达纲领是德国工人运动的一种纲领草案,...

    人工智能时代批判性思维能力的提升策略--思维图示的应用对小学生批判性思维能力提升的实证研究.pdf

    在人工智能时代,批判性思维能力的重要性日益凸显,它不仅有助于个体生存,也是有效参与社会活动和解决复杂问题的必备能力。批判性思维能力涉及对事物或问题的解释、分析、评价、推理、综合等多方面的能力,它要求...

    政治经济学批判导言读书笔记.pdf

    政治经济学批判导言读书笔记 政治经济学批判导言读书笔记是马克思主义政治经济学的重要著作之一,本文将对其进行详细的解读和分析。 生产的重要性 马克思在政治经济学批判导言中指出,物质生产的重要性是政治经济...

    参考资料-绿城:桂花城批判与思考.zip

    【标题】:“参考资料-绿城:桂花城批判与思考.zip”这一标题揭示了文件的主要内容,它涉及的是对绿城桂花城项目的一个深度分析和评价。绿城是中国知名的房地产开发商,而桂花城可能是其开发的一个住宅或商业项目。...

    批判性思维原理和方法.ppt

    "批判性思维原理和方法" 批判性思维是指一种合理的、反思性的思维方式,其目的是要决定我们的信念和行动。批判性思维者愿意探索艰难的问题,包括向流行的看法挑战。批判性思维的核心是主动评估观念的愿望。在某种...

    逻辑与批判性思维复习资料,内部包含完整的复习资料

    逻辑与批判性思维复习资料,内部包含完整的复习资料逻辑与批判性思维复习资料,内部包含完整的复习资料逻辑与批判性思维复习资料,内部包含完整的复习资料逻辑与批判性思维复习资料,内部包含完整的复习资料逻辑与...

    工科大学生创造力和批判性思维状况的调查

    创造力和批判性思维是在工作场所取得成功必不可少的两种能力,受到雇主的高度追捧。 但是,有证据表明,高级工程专业的学生会减少创造力和批判性思维。 这项研究试图了解新生的工科学生是否比高年级的工科学生更具...

    批判性思维-简明指南

    批判性思维原书

    批判理论视域中的互联网时代——网络批判理论概述.pdf

    批判理论视域中的互联网时代——网络批判理论概述.pdf

    批判性思维:掌控你的专业与个人生活的工具

    拒绝批判式思维,追求批判性思维。批判式思维是简单、粗暴的思维,不求甚解,只会往你头上戴帽子。批判性思维是你决定接受或拒绝某种观点的一种思考方式。

    基于批判性思维的计算机网络概论课程改革.pdf

    批判性思维不仅是一种思维品格,也是一种技能,包括批判精神和批判思维技能两个维度。批判精神体现了思维的主动性和独立性、怀疑精神、自信心、勇气以及坚韧性等特质。而批判思维技能则是进行有效价值判断、问题解决...

    高中生物学教学中基于深度学习的批判性思维培养研究.pdf

    "高中生物学教学中基于深度学习的批判性思维培养研究" 本文旨在探究高中生物学教学中基于深度学习的批判性思维培养策略,对学生批判性思维能力的培养进行了深入探究。通过对高中阶段生物教学中基于深度学习的批判性...

    批判性思维-(美)理查德.保罗

    批判性思维 CriticalThinking (美)理查德.保罗

    深度学习与批判性思维的研究.pdf

    南京市北京东路小学的实践经验表明,通过构建以国家课程为主的校本课程体系,实施以问题为导向的教学方式,以及探索有利于批判性思维发展的学习方式,可以在实践中有效地推动深度学习和批判性思维的融合。...

    逻辑与批判性思维训练PPT.zip

    《逻辑与批判性思维训练》PPT是一份深入探讨逻辑思维和批判性思考能力的教育资源。这份压缩包包含了丰富的教学材料,旨在帮助学习者提升在日常生活、学术研究以及工作中分析问题、评估信息和做出明智决策的能力。...

    政治经济学批判.doc

    政治经济学批判.doc

Global site tag (gtag.js) - Google Analytics