用户名: 密码: 免费注册 忘记密码? 网站地图 | 加入收藏 | 设为首页
首页 | 新闻 | 工具 | 系统 | 办公 | 聊天 | 多媒体 | 网页 | 运营 | 平面 | 欣赏 | 数据库 | 程序 | 服务器 | 组网
网页 | 3dmax | Ghost | Windows Xp| Dreamweaver | photoshop | Flash | office | Alexa | Css | QQ | Asp | PHP | Jsp | Access
Flash MX 2004入门 | 网站推广策略 | CorelDRAW入门 | ASP学习 | 网站建设大师功 | Word入门
  iTbulo.com > 学院 > 操作系统教程 > Windows2000教程 > 文章正文
《Undocumented Windows 2000 Secrets》翻译 --- 第二章(2)
iTbulo.COM 2005-7-29 ccxunmeng()

很多内核函数都使用统一的命名规则 ----PrefixOperationObject() 。例如, NtQueryInformationFile() 函数属于 Native API ,这是因为其 Nt 前缀,而且该函数显然针对一个文件对象执行了 QueryInformation 操作。但并不是所有函数都遵循这一规则,不过绝大多数都是如此。因此,可以很容易的通过函数的名称猜测其功能。

经常使用的数据类型

当编写与 Windows 2000 内核有关的软件时 --- 不管是和用户模式的 ntdll.dll 还是和内核模式的 ntoskrnl.exe ,你都必须处理几个基本的数据类型,而这些数据类型在 Win32 世界里非常少见。它们中的多数都会在本书中反复出现。下面的章节将介绍使用频率最高的数据类型。

整型

一般说来,整数类型有多个不同的变体。 Win32 SDK 的头文件和 SDK 文档使用了其专有的术语,这些术语很容易和 C/C++ 的基本类型以及一些派生类型相混淆。 2-3 列出了这些整数类型,以及它们之间的等价关系。在“ MASM ”列中,给出了微软宏汇编语言( MASM )使用的类型名称。 Win32 SDK 为 C/C++ 的基本数据类型定义了对应的 BYTE 、 WORD 、 DWORD 别名。“别名 1 ”和“别名 2 ”两列包含其经常使用的别名。例如, WCHAR 代表基础的 Unicode 字符类型。最后一列“有符号的”,列出了对应的有符号类型的常见别名。一定要记住 ANSI 字符类型 CHAR 是有符号的,而 Unicode 类型 WCHAR 是无符号的。当编译器将表达式或计算中的这些类型转换为整数类型时,这种不一致性将导致意外的错误。

表 2-3 最后一行的 MASM 的 TBYTE 类型(读做“ 10-byte ”)是一个 80 位的浮点数,用于高精度的浮点运算操作。 Microsoft Visual C/C++ 没有为 Win32 程序员提供对应的数据类型。需要注意的是, MASM 的 TBYTE 和 Win32 的 TBYTE (读做“ text byte ”)没有任何关系,后者只是一个用于转换的宏,根据源文件中是否有 #define UNICODE 而分别对应 CHAR 或 WCHAR 。

表 2-3. 等价的整数类型

位数

MASM

基本类型

别名 1

别名 2

有符号的

8

BTYE

unsigned char

UCHAR

CHAR

16

WORD

unsigned short

USHORT

WCHAR

SHORT

32

DWORD

unsigned long

ULONG

LONG

32

DWORD

unsigned int

UINT

INT

64

QWORD

unsigned __int64

ULONGLONG

DWORDLONG

LONGLONG

80

TBYTE

N/A

由于在 32 位编程环境中较难处理 64 位整数, Windows 2000 通常不提供 64 位的基本类型,如 __int64 或其派生类型。替代的, DDK 头文件 ntdef.h 中定义了一个精巧的 union 结构,可以将一个 64 位数解释为一对 32 位数或一个完整的 64 位数,参见 列表 2-3 给出了 LARGE_INTEGER 和 ULARGE_INTEGER 类型定义。该类型可分别表示有符号和无符号的整数。通过使用 LONGLONG/ULONGLONG (针对 64 位的 QuadPart 成员)或者 LONG/ULONG (针对 32 位的 HighPart 成员)来控制有无符号。

typedef union _LARGE_INTEGER

{

struct

{

ULONG LowPart;

LONG HighPart;

}

LONGLONG QuadPart;

} LARGE_INTEGER,*PLARGE_INTEGER;

typedef union _ULARGE_INTEGER

{

struct

{

ULONG LowPart;

ULONG HighPat;

}

ULONGLONG QuadPat;

} ULARGE_INTEGER,*PULARGE_INTEGER;

列表 2-3. LARGE_INTEGER 和 ULARGE_INTEGER

字符串

在 Win32 程序设计中,常使用 PSTR 和 PWSTR 来分别代替 ANSI 和 Unicode 字符串。 PSTR 被定义为 CHAR* , PWSTR 则定义为 WCHAR* (参见表 2-3 )。通过源文件中是否出现 #define UNICODE 指示符,附加的 PTSTR 类型分别对应 PSTR 或 PWSTR ,这样就可通过单一的源文件来维护应用程序的 ANSI 和 Unicode 版本。基本上,这些字符串都是简单的指向以零结尾的 CHAR 或 WCHAR 类型的数组。如果你常和 Windows 2000 内核打交道,你将必须处理一种很不同的字符串表示法。最常见的类型是 UNICODE_STRING ,这是一个第三方类型, 列表 2-4 给出了它的定义。

typedef struct _UNICODE_STRING

{

USHORT Length;

USHORT MaximumLength;

PWSTR Buffer;

} UNICODE_STRING,*PUNICODE_STRING;

typedef struct _STRING

{

USHORT Length;

USHORT MaximumLength;

PCHAR Buffer;

} STRING, *PSTRING;

typedef STRING ANSI_STRING, *PANSI_STRING;

typedef STRING OEM_STRING, *POEM_STRING;

列表 2-4. 字符串类型

Length 成员给出了当前字符串的字节数(注意,不是字符个数), MaximumLength 成员指出 Buffer 所指向内存块的大小,实际的字符串数据将保存在该内存块中。注意, MaximumLength 也是字节数。由于 Unicode 字符宽度为 16 位,所有其长度总是字符个数的两倍。通常, Buffer 指向的字符串都是以零结尾的。然而,有些内核模块可能仅依赖字符串的长度值,而不考虑结尾的 0 字符,这种情况下要小心处理。

Windows 2000 的 ANSI 字符串叫做 STRING ,如 列表 2-4 中所示。为了方便, nedef.h 分别定义了 ANSI_STRING 和 OEM_STRING 来代表使用不同代码页的 8 位字符串( ANSI 默认代码页为 1252 ; OEM 默认代码页为 437 )。不过, Windows 2000 内核使用的主要字符串类型还是 UNICODE_STRING 。你可能偶尔会碰到 8 位字符串。

《Undocumented

2-3 中,我给出了两个典型的 UNICODE_STRING 示例。左面的那个包含两个独立的内存块:一个 UNICODE_STRING 结构和一个 16 位 PWCHAR 类型的 Unicode 字符数组。这或许是在 Windows 2000 数据类型中最常见的字符串类型。右边的是一种频繁出现的特殊类型,在此种类型中, UNICODE_STRING 和 PWCHAR 数组位于同一个内存块中。有些内核函数,包括 Native API 内部使用的一些函数,都在连续的内存块中保存其返回的结构化的系统信息。如果数据中包含字符串,它们通常都存储在嵌入式的 UNICODE_STRING 中,如 2-3 右面所示。例如, NtQuerySystemInformation() 函数就频繁使用了这种特殊的字符串类型。

这些字符串结构不许要手工维护, ntdll.dll 和 ntoskrnl.exe 导出了一组丰富的运行时 API 函数,如 RtlCreateUnicodeString() 、 RtlInitUnicodeString() 、 RtlCopyUnicodeString() 等。通常, STRING 和 ANSI_STRING 也有对应的等价函数。这些函数中的大多数在 DDK 中都有文档记录,但其中有些没有。不过,很容易猜出这些未文档化的字符串函数的功能及其需要的参数。使用 UNICODE_STRING 、 STRING 的好处是,可以隐示的指定 Buffer 可容纳的字符串的大小。如果你给一个函数传递了一个 UNICODE_STRING 类型的字符串,而该函数需要适当改变该字符串的值,而这可能会增加该字符串的长度,那这个函数只需要简单的检查 MaximumLength 成员就可确定是否有足够的空间来存放结果。

结构体

个别的几个内核 API 函数期望其处理的对象有一个合适的 OBJECT_ATTRIBUTES 结构, 列表 2-5 给出了该结构的定义。例如, NtOpenFile() 函数没有 PWSTR 或 PUNICODE_STRING 参数用来指定要打开的文件的路径。替代的, OBJECT_ATTRIBUTES 结构中的 ObjectName 成员给出了该路径。通常,设置该结构很容易。除 ObjectName 外,还需要设置 Length 和 Attributes 成员。 Length 必须设置为: sizeof(OBJECT_ATTRIBUTES) , Attributes 是一组来自 ntdef.h 的 OBJ_* 常量。例如,如果你对象名称不区分大小写的话, Attributes 应设置为 OBJ_CASE_INSENSITIVE 。当然, ObjectName 成员是一个 UNICODE_STRING 指针,并不是通常的 PWSTR 。剩余的成员只要不使用,都可设置为 NULL 。

上一页  [1] [2] [3] 下一页

文章搜索
相关资讯
相关文章 相关下载
没有相关文章
焦点信息