上篇讲到通过DuplicateHandle共享内核对象的用法。下面先讲讲DuplicateHandle另一种用法:
假设一个进程对一个文件映射对象拥有读写权限。在程序的某个位置,调用一个函数,并希望它对文件只有读权限。应该使用DuplicateHandle为现有的对象创建一个新的只有读权限的句柄。然后把这个句柄传给该函数,而不是用原来的句柄。
int WINAPI_tWinMain(HINSTANCE hInstExe, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int nCmdShow){ HANDLE hFileMapRW = CreateFileMapping(INVALID_HANDLE_VALUE,NULL, PAGE_READWRITE,0,10240,NULL); HANDLE hFileMapRO; DuplicateHandle(GetCurrentProcess(), hFileMapRW, GetCurrentProcess(), &hFileMapRO, FILE_MAP_READ, FALSE,0); //...... }
下面讨论(内核)对象命名 中遗留下来的问题。
终端服务(Terminal Service) 和前面的描述有些差别。在运行终端服务的计算机中,有多个内核对象的命名空间。其中一个是全局的,主要由服务使用,每个客户端都能够访问。另外,每个客户端都有自己的内核对象命名空间。
//通过ProcessIdToSessionId获得该进程所在的终端会话。 DWORD processID = GetCurrentProcessId(); DWORD sessionID; if(ProcessIdToSessionId(processID, &sessioId)){ tprintf(TEXT("^^^^^^^")); }else{ //............. } //显示的将内核对象创建在全局命名空间中。 HANDLE h = CreateEvent(NULL,FALSE, FALSE,TEXT("Global\\MyName")); //显示的将内核对象创建在当前会话的命名空间中。 HANDLE h = CreateEvent(NULL,FALSE, FALSE,TEXT("Local\\MyName"));
对于一般的内核对象,我们最好应该模仿上面的方式,创建自己专有的命名空间,从而防止恶意程序的Dos攻击。