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);
当这些函数的最后一个参数lpszName为NULL时,系统将创建一个无名的内核对象。创建的无名对象,可以通过继承和复制来实现在进程间共享内核对象。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",之后检查内核对象类型,由于进程A和B创建的内核对象类型都是“互斥量”,所以系统就认为进程B对CreateMutex的调用成功了。系统在进程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_ACCESS和DUPLICATE_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/