第一章:错误处理
通过GetLastError函数获得更多的错误信息,或者在监视框中使用@err,hr(vs2005)获得错误信息,而不仅仅是错误编号。
第二章:字符和字符串处理
在应用程序中,应确保要么同时定义了UNICODE和_UNICODE,要么就一个都不定义,前者是Windows所用,后者是C运行库所用。
为了程序的安全应该尽量使用加_s后缀的字符串处理函数。
使用_s后缀的字符串函数后,如果超出缓冲区所允许的空间大小,会将整个字符串第一个字符设为'\0',其他字节填充0xfd。
StringCchCat,StringCchCopy,StringCchPrintf,StringCchPrintfEx系列函数,在缓冲区太小时会截断字符串,而不是像_s系列函数那样直接截断为空字符串。
调用_CrtSetReportMode(_CRT_ASSERT,0);后可以禁止可能由C运行时触发的所有DEBUG Assertion Failed对话框。
使用_countof来获取字符数,在字符串函数的声明中用Cch前缀来表示。用sizeof获取字符串的字节数,在字符串函数的声明中用Cb表示。
使用Windows函数MultiByteToWideChar将多字节字符串转换为宽字节字符串。
MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cbMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar);
其中uCodePage参数是一个代码页值,ANSI代码页为1252,日文代码页为932,简体中文代码页为936,950代表繁体中文。
dwFlags通常是0.
lpMultiByteStr指定要转换的字符串,cbMultiByte参数指定字符串的长度(字节数)。如果传给cbMultiByte参数的值是-1,函数便可自动判断源字符串的长度。
lpWideCharStr指定目标内存缓冲区,必须在cchWideChar中指定这个缓冲区的最大长度(字符数)。如果调用MultiByteToWideChar并给cchWideChar参数传入0,函数就不执行转换,而是返回一个宽字符数,包括\0。
通常使用以下步骤将一个多字节字符串转换为Unicode形式。
1.调用MultiByteToWideChar,lpWideCharStr参数传入NULL,cchWideChar参数传入0,cbMultiByte传入-1。
2.分配一块内存,它的大小是第一步调用的返回值乘以sizeof(wchar_t)。
3.再次调用MultiByteToWideChar,将第二步分配的内存地址传给lpWideCharStr,将第一步调用的返回值传给cchWideChar。
4.使用转换后的字符串。
5.释放Unicode字符串占用的内存块。
使用Windows函数WideCharToMultiByte将宽字符串转换为多字节字符串。
函数原型:
int WideCharToMultiByte(
UINT CodePage,
DWORD dwFlags,
LPWSTR lpWideCharStr,
int cchWideChar,
LPCSTR lpMultiByteStr,
int cchMultiByte,
LPCSTR lpDefaultChar,
PBOOL pfUsedDefaultChar );
使用方法类似于MultiByteToWideChar函数,不同点在于最后两个参数。当函数遇到一个不在CodePage指定的代码页中的文字时,会用 lpDefaultChar指向的字符替换。如果此参数为空,系统会使用默认字符进行替换,通常为问号,对文件名转换比较危险,因为问号是一个通配符。
pfUsedDefaultChar 指向一个布尔变量,如果至少有一个字符不能成功转换,此布尔变量将被设为TRUE,如果所有的都能成功转换,此变量将为FALSE。
第三章 内核对象
Windows的很多东西都是内核对象:访问令牌对象,事件对象,文件对象,文件映射对象,I/O完成端口对象,作业对象,邮件槽(mailslot)对象,互斥量(mutex)对象,管道(pipe)对象,进程对象,线程对象,信号量(semaphore)对象,可等待的计时器对象,线程池工厂对象等。
对象基本是通过Create开头的函数创建,通过Open系列函数进行进程间的共享,通过CloseHandle函数关闭使用。
对象内部都有一个引用计数器,每有一个进程获得对此对象的访问权后,此计数器加一。当某一个进程终止运行后,此计数器减一。所以,被某一进程所创建的对象,如果在过程中被其他线程使用了,其生存期可能会长过创建它的进程。只用当使用计数器变成0时,系统才销毁此对象。
跨进程共享内核对象的方法:
1.使用对象句柄继承。
2.为对象命名。
3.复制对象句柄。