Windows 核心编程(1~4.1)

来源:互联网 发布:创业如何组建团队 知乎 编辑:程序博客网 时间:2024/06/06 01:10
 
第一章 对程序错误的处理
在VC6的Watch窗口中键入”@err,hr”,就可以查看当前线程的最后错误代码。
Error Lookup GetLastError FormateMessage
Bits:
31-30
29
28
27-16
15-0
内容
Severity
Microsoft/ customer
保留
Facility code
Exception code
含义
0 = Success
1 = Informational
2 = Warning
3 = Error
0 = Microsoft-
defined code
1 = customer-
defined code
Must be 0
Microsoft-defined
Microsoft/customer-defined
HLOCAL hlocal = NULL;   // Buffer that gets the error message string

      
// Get the error code's textual description
      BOOL fOk = FormatMessage(
         FORMAT_MESSAGE_FROM_SYSTEM 
| FORMAT_MESSAGE_ALLOCATE_BUFFER, 
         NULL, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 
         (PTSTR) 
&hlocal, 0, NULL);

      
if (!fOk) {
         
// Is it a network-related error?
         HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, 
            DONT_RESOLVE_DLL_REFERENCES);

         
if (hDll != NULL) {
            FormatMessage(
               FORMAT_MESSAGE_FROM_HMODULE 
| FORMAT_MESSAGE_FROM_SYSTEM,
               hDll, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
               (PTSTR) 
&hlocal, 0, NULL);
            FreeLibrary(hDll);
         }

      }

      
if (hlocal != NULL) {
         SetDlgItemText(hwnd, IDC_ERRORTEXT, (PCTSTR) LocalLock(hlocal));
         LocalFree(hlocal);
      }

每个DLL(或exe)都有它自己的一组错误代码,可以使用Message Compiler将这组错误代码添加给该模块,并将一个资源添加给该模块。这就是Error Lookup工具允许你用Modules对话框进行的操作。
建立4级警告的代码如下:
#pragma warning(push, 3)
#include <Windows.h>
#pragma warning(pop)
#pragma warning(push, 4)
下面的选项强制链接程序寻找(w)WinMain进入点函数:
#pragma comment(linker, "/subsystem:Windows")
消息分流器、子控件宏和API宏包含在WindowsX.h中。
第二章 Unicode
_mbslen 返回字符个数
CharNext 返回字符串中的下一个字符的地址
CharPrev 返回字符串中的上一个字符的地址
IsDBCSLeadByteTRUE 该字节是不是DBCS字符的第一个字节 
WIN98不支持大多数UNICODE函数,WIN2000使用UNICODE开发,WINCE仅支持UNICODE。
Windows提供的经典字符串函数需包含ShlWApi头文件,形如StrCat。它也提供了一组对UNICODE字符串进行操作的函数,形如lstrcat。这两组函数都支持UNICODE版本和非UNICODE版本。
这些函数都跟标准C函数类似,但lstrcmp和lstrcmpi是调用CompareString来实现的。
int CompareString(
LCID lcid,                
//语言设置,调用GetThreadLocale取得
DWORD fdwStyle, //一些指示比较方式的标志,如NORM_IGNORECASE
PCWSTR pString1,
int cch1,
PCTSTR pString2,
int cch2);
      CharLower和CharUpper可以转换单个字符也可以转换一个字符串,还能处理带重音符号的字符。处理单个字符时使用方式如下:
       TCHAR cLowerCaseChar = CharLower((PTSTR)szString[0]);
CharLowerBuff和CharUpperBuff 可处理非0结束的情况。
IsCharAlpha系列函数也考虑了语言设置的问题。
微软对PRINTF系列函数增加了一些特殊的用法,如S的大小写可用来区分UNICODE和ANSI。
IsTextUnicode可判断文本是不是UNICODE码,但不保证其正确性。
第三章 内核对象
内核对象的句柄是进程相关的。内核对象的使用计数跟COM的类似,它会在进程结束时自动减少使用计数
用于创建内核对象的函数几乎都有一个指向SECURITY_ATTRIBUTES结构的指针作为参数,用于指定该对象的安全性,通常传递NULL,表示使用默认安全性,即管理员组和创建者都有完全访问权限,其它人无权访问。当你想要获得对相应的一个内核对象的访问权时,必须设定要对该对象执行什么操作。
每个进程都有一个内核对象句柄表,记录对象的指针,权限和标志,对象的句柄用来在句柄表中查找相应对象的信息。
大多数内核对象创建函数返回NULL表示失败,但也有例外,如CreateFile则返回INVALID_HANDLE_VALUE。
当进程关闭时,系统可以保证不留下任何对象。
SECURITY_ATTRIBUTES结构的bInheritHandle成员标识创建的对象可以被继承,CreateProcess函数的bInheritHandles参数为TRUE时那些可继承的对象句柄表项将被复制到子进程中,并增加对象的使用计数。传递句柄的方式有命令行参数、消息(用WaitForInputIdle等待子进程完成初始化)和环境变量。
SetHandleInformation可用来改变对象句柄的标志,除了继承标志HANDLE_FLAG_INHERIT外,与每个句柄都相关的标志还有防止他人关闭句柄的HANDLE_FLAG_PROTECT_FROM_CLOSE。
命名对象用Create函数打开时将忽略名字以外的参数,此时调用GetLastError将返回ERROR_ALREADY_EXISTS,不需要创建时可用Open函数,如
HANDLE OpenMutex(DWORD dwDesiredAccess, BOOL bInheritHandle, PCTSTR pszName);
所有内核对象共享一个名字空间,终端服务器为每个会话创建一个名字空间,要强制使用特定的名字空间,可通过Global/和Local/关键字。
BOOL DuplicateHandle(
    HANDLE hSourceProcessHandle, 
    HANDLE hSourceHandle,
    HANDLE hTargetProcessHandle, 
    PHANDLE phTargetHandle, 
    DWORD dwDesiredAccess, 
    BOOL bInheritHandle, 
    DWORD dwOptions);
此函数用来将一个进程中的对象句柄复制到另一个进程中,最后一个参数可以为0或DUPLICATE_SAME_ACCESS 和 DUPLICATE_CLOSE_SOURCE的组合。此函数常用在一个进程想将内核对象的访问权赋予另一个进程或改变句柄对对象的访问权限时。
第四章 进程
/SUBSYSTEM:WINDOWS /SUBSYSTEM:CONCOLE
启动函数完成如下功能:
• 检索指向新进程的完整命令行的指针。
• 检索指向新进程的环境变量的指针。
• 对C / C + +运行期的全局变量进行初始化。如果包含了S t d L i b . h文件,代码就能访问这些变量。
• 对C运行期内存单元分配函数( m a l l o c和c a l l o c)和其他低层输入/输出例程使用的内存栈进行初始化。
• 为所有全局和静态C + +类对象调用构造函数。
当进入点函数返回时,启动函数便调用C运行期的e x i t函数,将返回值( n M a i n R e t Va l)传递给它。E x i t函数负责下面的操作:
• 调用由_ o n e x i t函数的调用而注册的任何函数。
• 为所有全局的和静态的C + +类对象调用析构函数。
• 调用操作系统的E x i t P r o c e s s函数,将n M a i n R e t Va l传递给它。这使得该操作系统能够撤消进程并设置它的e x i t代码。
HMODULE与HINSTANCE是完全相同的对象。都是系统将可执行文件的映像加载到进程的地址空间时使用的基本地址空间。因为WIN98底部4M禁止访问,VC默认使用0X400000,可以使用/BASE:address改变。
GetModuleHandle参数为空时得到应用程序句柄,即使在DLL中调用。