Windows核心编程学习笔记一(内核对象)

Windows核心编程学习笔记一(内核对象)

1.windows95上部分Win32实际上不可用,如:CreateRemoteThread函数,在Windows95上调用该函数时返回结果是NULL。(为什么会有部分函数不可用呢?答案:为了使Windows95适合4MB的内存的计算机。Windows95具体不支持的Win32有:Win32的一些异步文件I/O函数、高度函数、注册函数、安全函数和事件记录函数,这些函数虽然在Windows95上有,但是它们是有限制地实现的)


2.内核对象:内核对象的数据结构只能由内核访问,应用程序不能在内存中定位这些数据结构和直接改变它们的内容。(内核对象通过调用相应的Win32函数产生,并返回一个标识该对象的句柄,注:该句柄进程相关。每一个内核对象实际上是由内核分配的一块内存,而只能由内核访问。这块内存就是一块数据结构,它包含的成员是关于该对象的信息。内核对象由内核控制何时释放,而不是由调用它的进程,每一个内核对象的数据中都有一个进程引用计数,当某进行创建了一个内核对象时,该内核对象中的引用计数被置为1,之后要是有其它进程访问该内核对象时,引用计数加1,当所有访问内核对象的进程都释放,引用计数为0时,该内核对象由内核释放)

3.用户及图形接口对象:菜单、窗口、鼠标、光标、刷子、字体等对象。可以使用创建对象的函数来区分哪个是内核对象,哪个是用户及图形接口对象,在内核对象创建函数的参数中大多都有LPSECURITY_ATTRIBUTES类型的参数,相反用户对象图形接口对象无此类型参数。

4.内核对象共享:

(1)内核对象的共继承:一个子进程继承父进程中(可继承的)内核对象。如果父进程想指定某个子进程继承它的内核对象该怎么办呢?可以通过函数SetHandleInformation(HANDLE hObject,DWORD dwMask,DWORD dwFlags);来实现。

具体方法:

1.使子进程可以继承父进程的内核对象:SetHandleInformation(hObj,HANDLE_F

LAG_INHERIT,HANDLE_FLAG_INHERIT);//注:这种操作也可以称为打开内核对象

句柄继承标志。

2.子进程不能继承父进程的内核对象方法:SetHandleInformation(hObj,HANDLE

_FLAG_INHERIT,0);//注:这个操作也可以称为关闭内核对象继承标志

另注:判断某个句柄是否可继承方法:

DWORD dwFlags;

GetHandleInformation(hObj,&dwFlags);

BOOL fHandleIsInheritable = (0!=(dwFlags &HANDLE_FLAG_INHERITABLE));

其中函数GetHandleInformation(HANDLE hObj,LPDWORD lpdwFlags)函数是用来返回当前句柄标志到lpdwFlags指向的DWORD中。

(2)命名对象:使用下列函数可以创建一个命名的内核对象,

HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpszName);

HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,BOOL bInitialState,LPCTSTR lpszName);

HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,LONG lMaximumCount,LPCTSTR lpszName);

HANDLE CreateWaitableTimer(LPSECURITY_ATTRIBUTES lpTimerAttributes,BOOL bManualReset,LPCTSTR lpszName);

HANDLE CreateFileMapping(HANDLE hFile,LPSECURITY_ATTRIBUTES lpFileMappingAttributes,DWORD flProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,LPCTSTR lpszName);

当这些函数的最后一个参数lpszNameNULL时,系统将创建一个无名的内核对象。创建的无名对象,可以通过继承和复制来实现在进程间共享内核对象。lpszName参数:它的最大长度为MAX_PATH(260个字符),且不能包含左斜杠

小常识: 得到执行错误信息可以通过函数GetLastError();

例如:DWORD dwErrorCode = GetLastError();

那么如何使用“命名的内核对象来共享内核对象呢?”

方法及理论实质:通过具体例子说明,假设进程A创建一个内核对象:

HANDLE hMutexProcessA = CreateMutex(NULL,FALSE,"UUXAMutex");之后进程B也同样:HANDLE hMutexProcessB = CreateMutex(NULL,FALSE,"UUXAMutex");创建了一个与进程A相同的内核对象,那么结果进程B是否成功创建内核对象了呢?系统是这样处理这种情况的,首先系统检查是否存在一个名称为"UUXAMutex"的内核对象,经检查后呢,发现已经存在内核对象"UUXAMutex",之后检查内核对象类型,由于进程AB创建的内核对象类型都是“互斥量”,所以系统就认为进程BCreateMutex的调用成功了。系统在进程B的句柄表中找到一个空表项,然后初始化该表项指向已经存在的内核对象。

判断一个进程是否真正的创建了一个新的内核对象可以使用GetLastError来判断。

HANDLE hMutex = CreateMutex(NULL,FALSE,"SomeMutex");

if (GetLastError() == ERROR_ALREADY_EXISTS) {

}else{};

(3)复制对象句柄:通过函数BOOL DuplicateHandle(HANDLE hSourceProcessHandle,HANDLE hSourceHandle,HANDLE hTargetProcessHandle,LPHANDLE lpTargetHandle,DWORD dwDesireAccess,BOOL bInheritHandle,DWORD dwOptions);

参数:dwOptions可以是0或是DUPLICATE_SAME_ACCESSDUPLICATE_CLOSE_SOURCE

举例:如果进程A想让进程B得到自己能够访问的一个内核对象的访问权限,那么该如何做呢?如下所示:

HANDLE hObjProcessA = CreateMutex(NULL,FALSE,NULL);

HANDLE hProcessB = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessIdB);

HANDLE hObjProcessB;

DuplicateHandle(GetCurrentProcess(),hObjProcessA,hProcessB,&hObjProcessB,0,FALSE,DUPLICATE_SAME_ACCESS);

CloseHandle(hProcessB);

CloseHandle(hObjProcessA);

 

来自:http://uuxa.itpub.net/

你可能感兴趣的:(Windows核心编程学习笔记一(内核对象))