【windows】windows核心编程读书笔记

关于Unicode编码

微软对对U n i c o d e支持的情况:

• Windows 2000既支持U n i c o d e,也支持A N S I,因此可以为任意一种开发应用程序。

• Windows 98只支持A N S I,只能为A N S I开发应用程序。

• Windows CE只支持U n i c o d e,只能为U n i c o d e开发应用程序。

 

C运行期库对U n i c o d e的支持

为了利用U n i c o d e字符串,定义了一些数据类型。标准的C头文件S t r i n g . h已经作了修改,以便定义一个名字为w c h a r_ t的数据类型,它是一个U n i c o d e字符的数据类型:typedef unsigned short wchar_t;

标准的ANSI C字符串函数和它们的等价U n i c o d e函数,请注意,所有的U n i c o d e函数均以w c s开头,w c s是宽字符串的英文缩写。若要调用U n i c o d e函数,只需用前缀w c s来取代A N S I字符串函数的前缀s t r即可。对于包含了对s t r函数或w c s函数进行显式调用的代码来说,无法非常容易地同时为A N S I和U n i c o d e对这些代码进行编译。本章前面说过,可以创建同时为A N S I和U n i c o d e进行编译的单个源代码文件。若要建立双重功能,必须包含T C h a r. h文件,而不是包含S t r i n g . h文件。

T C h a r. h文件的唯一作用是帮助创建A N S I / U n i c o d e通用源代码文件。它包含你应该用在源代码中的一组宏,而不应该直接调用s t r函数或者w c s函数。

如果在编译源代码文件时定义了_ U N I C O D E,这些宏就会引用w c s这组函数。如果没有定义_ U N I C O D E,那么这些宏将引用s t r

这组宏。

 

定义Unicode字符串

_ T E X T宏也在T C h a r. h文件中做了定义。如果定义了_ U N I C O D E,那么_ T E X T定义为下面的形

式:#define _TEXT(x) L ## x

如果没有定义_ U N I C O D E,_ T E X T将定义为

#define _TEXT(x) x

 

Wi n d o w s定义的U n i c o d e数据类型

W C H A R    U n i c o d e字符

P W S T R     指向U n i c o d e字符串的指针

P C W S T R   指向一个恒定的U n i c o d e字符串的指针

这些数据类型是指U n i c o d e字符和字符串。Wi n d o w s头文件也定义了A N S I / U n i c o d e通用数据类型P T S T RP C T S T R。这些数据类型既可以指A N S I字符串,也可以指U n i c o d e字符串,这取决于当编译程序模块时是否定义了U N I C O D E宏。

请注意,这里的U N I C O D E宏没有前置的下划线。_ U N I C O D E宏用于C运行期头文件,而U N I C O D E宏则用于Wi n d o w s头文件。当编译源代码模块时,通常必须同时定义这两个宏。

系统函数调用

在我们的代码中,通常只包含了对C r e a t e Wi n d o w E x的调用,而不是直接调用

C r e a t e Wi n d o w E x W或者C r e a t e Wi n d o w E x A。在Wi n U s e r. h文件中,C r e a t e Wi n d o w E x实际上是定义为下面这种形式的一个宏:

 

如果要创建其他软件开发人员将要使用的动态链接库( D L L),请考虑使用下面的方法。

在D L L中提供两个输出函数。一个是A N S I版本,另一个是U n i c o d e版本。在A N S I版本中,只需要分配内存,执行必要的字符串转换,并调用该函数的U n i c o d e版本(本章后面部分介绍这个进程)。

当资源编译器对你的所有资源进行编译时,输出文件是资源的二进制文件。资源(字符串

表、对话框模板和菜单等)中的字符串值总是写作U n i c o d e字符串。

U n i c o d eA N S I之间转换字符串

Wi n d o w s函数M u l t i B y t e To Wi d e C h a r用于将多字节字符串转换成宽字符串。

 

关于内核对象

简介

每个内核对象都只是一个内存块由操作系统内核分配并只能由操作系统内核访问,它是一个数据结构,应用程序不能在内存定位这些数据结构并直接更改其内容。只能利用windows系统提供的函数来操作这些结构。

调用一个创建内核对象的函数后会翻译一个句柄,它标识所创建的对象。32为系统中是一个32位值;64位windows进程中是64位值。

注意:句柄是进程相关的,所以如果将句柄值传给另个进程中的线程,那么另一个进程对句柄来发出调用时就可能失败,它甚至会引用到另个进程中完全不同的内核对象。 如果需要多个进程共享一个内核对象需要使用“跨进程边界共享内核对象”机制。

内核对象的所有者是操作系统而非进程,进程调用一个函数来创建了一个内核对象然后进程终止内核对象不一定会立即销毁,大多数情况下是会销毁的,但假如另一个进程正在使用我们进程创建的内核对象那么在其他进程停止使用它之前是不会销毁的。

内核对象包含一个使用计数只能当使用计数为0时才会释放。

 

创建

用于创建内核对象的所有函数几乎都有一个SECURITY_ATTRIBUTES结构的指针类型作为参数,大多数程序只是为这个参数传入NULL,这样创建的内核对象具有默认的安全性——取决于当前进程的安全令牌。

访问

如果访问现有的内核对象(而不是新建),必须指定对此对象执行哪些操作。被访问内核对象返回一个有效句柄之前会先执行安全检查,如果访问登录的用户被允许访问现有对象则返回有效句柄否则返回NULL。

很多老版本的windows设计的应用程序之所以不能在vista上工作就是因为实现这些程序时没有考虑安全性。

忽视正确的安全访问标识是很多开发人员最大的失误之一,只要使用了正确的安全访问标识我们程序就能很容易在不同版本的windows之间移植。

例如在vista中我们需要关注“用户账户控制”即UAC特性。默认情况下为了安全起见,UAC会强制应用程序在一个受限的上下文运行,即使当前用户是administrators组的成员。

除了内核对象,应程序可能还要使用其他类型的对象,比如菜单、窗口、鼠标光标、这些有些属于用户对象有些是GDI对象,首次编程很难区分是不是内核对象,简单的方式就是查看创建这个对象时有没有允许指定安全属性信息作为参数。类似CreateFileMapping函数。用户对象或GDI对象的创建函数都没有这个参数。

进程内核对象句柄表

一个进程在初始化时,系统将为它分配一个句柄表(handle table)。这个句柄表仅供内核对象使用,不适用于用户对象或GDI对象。字段结构大概如下:

索引   执行内核对象内存块的指针   访问掩码      标识

由于句柄值实际是作为进程句柄表的索引来使用的,所以这些句柄是与当前这个进程相关的,无法供其他进程使用。如果真的在其他进程中使用它那么实际上引用的只是那个进程的句柄表中位于同一个索引的内核对象。

关闭内核对象

无论以什么方式创建内核对象,我们都要调用closeHandle向系统表明我们已经结束使用对象,系统会先验证句柄的有效性然后清除内核表中对应的记录,无论内核对象当前是否销毁,我们的进程都不能再访问那个内核对象;如果内核对象的计数没有递减至0,它就不会被销毁。这完全是正常的。

程序运行时,它可能会泄漏内核对象,但当进程终止运行,系统能保证一切都被正确清除,这适用于所有的内核对象、资源及内存块。

跨进程共享内核对象

1、使用对象句柄继承

  只有在进程之间有一个父子关系的时候才可以使用对象句柄继承。这种情况下,父进程有一个或多个内核对象可以使用,而且父进程决定生成一个子进程并允许子进程访问父进程的内核对象。实现需要如下步骤

 a、创建对象时构造SECURITY_ATTRIBUTE结构并且把bInheritHandle成员的值赋值为ture并传入。

 b、在创建createProcess方法时将bInheritHandle参数设置为true,默认是fasle,false是向系统表明:我们不希望子进程集成父进程句柄表中的“可继承的句柄”。

如果设置为true系统在创建子进程时就会遍历父进程的句柄表,对它的每一项进程检查。凡是包含一个有效的“可继承的句柄”的项都会被完整的复制到子进程的句柄表相同的位置上。这是一个非常重要的设计因为句柄的值就是对应内核对象在句柄表的位置序号(索引)。除此之外系统还会递增内核对象的使用计数,如果需要销毁对象父子进程都要对这个对象调用closeHandle,要么父子进程都终止执行。

 

3.3.2 改变句柄的标志

3.3.3 为对象命名

这些细节无关大局的就不看了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值